1# 2# This file and its contents are supplied under the terms of the 3# Common Development and Distribution License ("CDDL"), version 1.0. 4# You may only use this file in accordance with the terms of version 5# 1.0 of the CDDL. 6# 7# A full copy of the text of the CDDL should have accompanied this 8# source. A copy of the CDDL is also available via the Internet at 9# http://www.illumos.org/license/CDDL. 10# 11 12# 13# Copyright (c) 2017, 2018 by Delphix. All rights reserved. 14# 15 16. $STF_SUITE/include/libtest.shlib 17. $STF_SUITE/tests/functional/removal/removal.kshlib 18 19# 20# In general all the tests related to the pool checkpoint can 21# be divided into two categories. TESTS that verify features 22# provided by the checkpoint (e.g. checkpoint_rewind) and tests 23# that stress-test the checkpoint (e.g. checkpoint_big_rewind). 24# 25# For the first group we don't really care about the size of 26# the pool or the individual file sizes within the filesystems. 27# This is why these tests run directly on pools that use a 28# "real disk vdev" (meaning not a file based one). These tests 29# use the $TESTPOOL pool that is created on top of $TESTDISK. 30# This pool is refered to as the "test pool" and thus all 31# the tests of this group use the testpool-related functions of 32# this file (not the nested_pools ones). 33# 34# For the second group we generally try to bring the pool to its 35# limits by increasing fragmentation, filling all allocatable 36# space, attempting to use vdevs that the checkpoint spacemap 37# cannot represent, etc. For these tests we need to control 38# almost all parameters of the pool and the vdevs that back it 39# so we create them based on file-based vdevs that we carefully 40# create within the $TESTPOOL pool. So most of these tests, in 41# order to create this nested pool sctructure, generally start 42# like this: 43# 1] We create the test pool ($TESTPOOL). 44# 2] We create a filesystem and we populate it with files of 45# some predetermined size. 46# 3] We use those files as vdevs for the pool that the test 47# will use ($NESTEDPOOL). 48# 4] Go on and let the test run and operate on $NESTEDPOOL. 49# 50 51# 52# These disks are used to back $TESTPOOL 53# 54TESTDISK="$(echo $DISKS | cut -d' ' -f1)" 55EXTRATESTDISK="$(echo $DISKS | cut -d' ' -f2)" 56 57FS0=$TESTPOOL/$TESTFS 58FS1=$TESTPOOL/$TESTFS1 59FS2=$TESTPOOL/$TESTFS2 60 61FS0FILE=/$FS0/$TESTFILE0 62FS1FILE=/$FS1/$TESTFILE1 63FS2FILE=/$FS2/$TESTFILE2 64 65# 66# The following are created within $TESTPOOL and 67# will be used to back $NESTEDPOOL 68# 69DISKFS=$TESTPOOL/disks 70FILEDISKDIR=/$DISKFS 71FILEDISK1=/$DISKFS/dsk1 72FILEDISK2=/$DISKFS/dsk2 73FILEDISKS="$FILEDISK1 $FILEDISK2" 74 75# 76# $NESTEDPOOL related variables 77# 78NESTEDPOOL=nestedpool 79NESTEDFS0=$NESTEDPOOL/$TESTFS 80NESTEDFS1=$NESTEDPOOL/$TESTFS1 81NESTEDFS2=$NESTEDPOOL/$TESTFS2 82NESTEDFS0FILE=/$NESTEDFS0/$TESTFILE0 83NESTEDFS1FILE=/$NESTEDFS1/$TESTFILE1 84NESTEDFS2FILE=/$NESTEDFS2/$TESTFILE2 85 86# 87# In the tests that stress-test the pool (second category 88# mentioned above), there exist some that need to bring 89# fragmentation at high percentages in a relatively short 90# period of time. In order to do that we set the following 91# parameters: 92# 93# * We use two disks of 1G each, to create a pool of size 2G. 94# The point is that 2G is not small nor large, and we also 95# want to have 2 disks to introduce indirect vdevs on our 96# setup. 97# * We enable compression and set the record size of all 98# filesystems to 8K. The point of compression is to 99# ensure that we are not filling up the whole pool (that's 100# what checkpoint_capacity is for), and the specific 101# record size is set to match the block size of randwritecomp 102# which is used to increase fragmentation by writing on 103# files. 104# * We always have 2 big files present of 512M each, which 105# should account for 40%~50% capacity by the end of each 106# test with fragmentation around 50~60%. 107# * At each file we attempt to do enough random writes to 108# touch every offset twice on average. 109# 110# Note that the amount of random writes per files are based 111# on the following calculation: 112# 113# ((512M / 8K) * 3) * 2 = ~400000 114# 115# Given that the file is 512M and one write is 8K, we would 116# need (512M / 8K) writes to go through the whole file. 117# Assuming though that each write has a compression ratio of 118# 3, then we want 3 times that to cover the same amount of 119# space. Finally, we multiply that by 2 since our goal is to 120# touch each offset twice on average. 121# 122# Examples of those tests are checkpoint_big_rewind and 123# checkpoint_discard_busy. 124# 125FILEDISKSIZE=1g 126DISKSIZE=1g 127BIGFILESIZE=512M 128RANDOMWRITES=400000 129 130 131# 132# Assumes create_test_pool has been called beforehand. 133# 134function setup_nested_pool 135{ 136 log_must zfs create $DISKFS 137 138 log_must mkfile $DISKSIZE $FILEDISK1 139 log_must mkfile $DISKSIZE $FILEDISK2 140 141 log_must zpool create $NESTEDPOOL $FILEDISKS 142} 143 144function setup_test_pool 145{ 146 log_must zpool create $TESTPOOL "$TESTDISK" 147} 148 149function setup_nested_pools 150{ 151 setup_test_pool 152 setup_nested_pool 153} 154 155function cleanup_nested_pool 156{ 157 log_must zpool destroy $NESTEDPOOL 158 log_must rm -f $FILEDISKS 159} 160 161function cleanup_test_pool 162{ 163 log_must zpool destroy $TESTPOOL 164} 165 166function cleanup_nested_pools 167{ 168 cleanup_nested_pool 169 cleanup_test_pool 170} 171 172# 173# Remove and re-add each vdev to ensure that data is 174# moved between disks and indirect mappings are created 175# 176function introduce_indirection 177{ 178 for disk in ${FILEDISKS[@]}; do 179 log_must zpool remove $NESTEDPOOL $disk 180 log_must wait_for_removal $NESTEDPOOL 181 log_mustnot vdevs_in_pool $NESTEDPOOL $disk 182 log_must zpool add $NESTEDPOOL $disk 183 done 184} 185 186FILECONTENTS0="Can't wait to be checkpointed!" 187FILECONTENTS1="Can't wait to be checkpointed too!" 188NEWFILECONTENTS0="I survived after the checkpoint!" 189NEWFILECONTENTS2="I was born after the checkpoint!" 190 191function populate_test_pool 192{ 193 log_must zfs create -o compression=lz4 -o recordsize=8k $FS0 194 log_must zfs create -o compression=lz4 -o recordsize=8k $FS1 195 196 echo $FILECONTENTS0 > $FS0FILE 197 echo $FILECONTENTS1 > $FS1FILE 198} 199 200function populate_nested_pool 201{ 202 log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS0 203 log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS1 204 205 echo $FILECONTENTS0 > $NESTEDFS0FILE 206 echo $FILECONTENTS1 > $NESTEDFS1FILE 207} 208 209function test_verify_pre_checkpoint_state 210{ 211 log_must zfs list $FS0 212 log_must zfs list $FS1 213 log_must [ "$(cat $FS0FILE)" = "$FILECONTENTS0" ] 214 log_must [ "$(cat $FS1FILE)" = "$FILECONTENTS1" ] 215 216 # 217 # If we've opened the checkpointed state of the 218 # pool as read-only without rewinding on-disk we 219 # can't really use zdb on it. 220 # 221 if [[ "$1" != "ro-check" ]] ; then 222 log_must zdb $TESTPOOL 223 fi 224 225 # 226 # Ensure post-checkpoint state is not present 227 # 228 log_mustnot zfs list $FS2 229 log_mustnot [ "$(cat $FS0FILE)" = "$NEWFILECONTENTS0" ] 230} 231 232function nested_verify_pre_checkpoint_state 233{ 234 log_must zfs list $NESTEDFS0 235 log_must zfs list $NESTEDFS1 236 log_must [ "$(cat $NESTEDFS0FILE)" = "$FILECONTENTS0" ] 237 log_must [ "$(cat $NESTEDFS1FILE)" = "$FILECONTENTS1" ] 238 239 # 240 # If we've opened the checkpointed state of the 241 # pool as read-only without rewinding on-disk we 242 # can't really use zdb on it. 243 # 244 if [[ "$1" != "ro-check" ]] ; then 245 log_must zdb $NESTEDPOOL 246 fi 247 248 # 249 # Ensure post-checkpoint state is not present 250 # 251 log_mustnot zfs list $NESTEDFS2 252 log_mustnot [ "$(cat $NESTEDFS0FILE)" = "$NEWFILECONTENTS0" ] 253} 254 255function test_change_state_after_checkpoint 256{ 257 log_must zfs destroy $FS1 258 log_must zfs create -o compression=lz4 -o recordsize=8k $FS2 259 260 echo $NEWFILECONTENTS0 > $FS0FILE 261 echo $NEWFILECONTENTS2 > $FS2FILE 262} 263 264function nested_change_state_after_checkpoint 265{ 266 log_must zfs destroy $NESTEDFS1 267 log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS2 268 269 echo $NEWFILECONTENTS0 > $NESTEDFS0FILE 270 echo $NEWFILECONTENTS2 > $NESTEDFS2FILE 271} 272 273function test_verify_post_checkpoint_state 274{ 275 log_must zfs list $FS0 276 log_must zfs list $FS2 277 log_must [ "$(cat $FS0FILE)" = "$NEWFILECONTENTS0" ] 278 log_must [ "$(cat $FS2FILE)" = "$NEWFILECONTENTS2" ] 279 280 log_must zdb $TESTPOOL 281 282 # 283 # Ensure pre-checkpointed state that was removed post-checkpoint 284 # is not present 285 # 286 log_mustnot zfs list $FS1 287 log_mustnot [ "$(cat $FS0FILE)" = "$FILECONTENTS0" ] 288} 289 290function fragment_before_checkpoint 291{ 292 populate_nested_pool 293 log_must mkfile -n $BIGFILESIZE $NESTEDFS0FILE 294 log_must mkfile -n $BIGFILESIZE $NESTEDFS1FILE 295 log_must randwritecomp $NESTEDFS0FILE $RANDOMWRITES 296 log_must randwritecomp $NESTEDFS1FILE $RANDOMWRITES 297 298 # 299 # Display fragmentation on test log 300 # 301 log_must zpool list -v 302} 303 304function fragment_after_checkpoint_and_verify 305{ 306 log_must zfs destroy $NESTEDFS1 307 log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS2 308 log_must mkfile -n $BIGFILESIZE $NESTEDFS2FILE 309 log_must randwritecomp $NESTEDFS0FILE $RANDOMWRITES 310 log_must randwritecomp $NESTEDFS2FILE $RANDOMWRITES 311 312 # 313 # Display fragmentation on test log 314 # 315 log_must zpool list -v 316 317 log_must zdb $NESTEDPOOL 318 log_must zdb -kc $NESTEDPOOL 319} 320 321function wait_discard_finish 322{ 323 typeset pool="$1" 324 325 typeset status 326 status=$(zpool status $pool | grep "checkpoint:") 327 while [ "" != "$status" ]; do 328 sleep 5 329 status=$(zpool status $pool | grep "checkpoint:") 330 done 331} 332 333function test_wait_discard_finish 334{ 335 wait_discard_finish $TESTPOOL 336} 337 338function nested_wait_discard_finish 339{ 340 wait_discard_finish $NESTEDPOOL 341} 342 343# 344# Creating the setup for the second group of tests mentioned in 345# block comment of this file can take some time as we are doing 346# random writes to raise capacity and fragmentation before taking 347# the checkpoint. Thus we create this setup once and save the 348# disks of the nested pool in a temporary directory where we can 349# reuse it for each test that requires that setup. 350# 351SAVEDPOOLDIR="/var/tmp/ckpoint_saved_pool" 352 353function test_group_premake_nested_pools 354{ 355 setup_nested_pools 356 357 # 358 # Populate and fragment the pool. 359 # 360 fragment_before_checkpoint 361 362 # 363 # Export and save the pool for other tests. 364 # 365 log_must zpool export $NESTEDPOOL 366 log_must mkdir $SAVEDPOOLDIR 367 log_must cp $FILEDISKS $SAVEDPOOLDIR 368 369 # 370 # Reimport pool to be destroyed by 371 # cleanup_nested_pools function 372 # 373 log_must zpool import -d $FILEDISKDIR $NESTEDPOOL 374} 375 376function test_group_destroy_saved_pool 377{ 378 log_must rm -rf $SAVEDPOOLDIR 379} 380 381# 382# Recreate nested pool setup from saved pool. 383# 384function setup_nested_pool_state 385{ 386 setup_test_pool 387 388 log_must zfs create $DISKFS 389 log_must cp $SAVEDPOOLDIR/* $FILEDISKDIR 390 391 log_must zpool import -d $FILEDISKDIR $NESTEDPOOL 392} 393