1#!/bin/ksh -p 2# SPDX-License-Identifier: CDDL-1.0 3 4# 5# This file and its contents are supplied under the terms of the 6# Common Development and Distribution License ("CDDL"), version 1.0. 7# You may only use this file in accordance with the terms of version 8# 1.0 of the CDDL. 9# 10# A full copy of the text of the CDDL should have accompanied this 11# source. A copy of the CDDL is also available via the Internet at 12# http://www.illumos.org/license/CDDL. 13# 14 15# 16# Copyright (c) 2017 by Delphix. All rights reserved. 17# 18 19. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib 20 21# 22# DESCRIPTION: 23# It should be possible to rewind a pool beyond a configuration change. 24# 25# STRATEGY: 26# 1. Create a pool. 27# 2. Generate files and remember their hashsum. 28# 3. Note last synced txg. 29# 4. Take a snapshot to make sure old blocks are not overwritten. 30# 5. Perform zpool add/attach/detach/remove operation. 31# 6. Change device paths if requested and re-import pool. 32# 7. Checkpoint the pool as one last attempt to preserve old blocks. 33# 8. Overwrite the files. 34# 9. Export the pool. 35# 10. Verify that we can rewind the pool to the noted txg. 36# 11. Verify that the files are readable and retain their old data. 37# 38# DISCLAIMER: 39# This test can fail since nothing guarantees that old MOS blocks aren't 40# overwritten. Snapshots protect datasets and data files but not the MOS. 41# sync_some_data_a_few_times interleaves file data and MOS data for a few 42# txgs, thus increasing the odds that some txgs will have their MOS data 43# left untouched. 44# 45 46verify_runnable "global" 47 48function custom_cleanup 49{ 50 set_vdev_validate_skip 0 51 cleanup 52 log_must set_tunable64 VDEV_MIN_MS_COUNT 16 53} 54 55log_onexit custom_cleanup 56 57function test_common 58{ 59 typeset poolcreate="$1" 60 typeset addvdevs="$2" 61 typeset attachargs="${3:-}" 62 typeset detachvdev="${4:-}" 63 typeset removevdev="${5:-}" 64 typeset finalpool="${6:-}" 65 typeset retval=1 66 67 typeset poolcheck="$poolcreate" 68 69 log_must zpool create $TESTPOOL1 $poolcreate 70 71 log_must generate_data $TESTPOOL1 $MD5FILE 72 73 # syncing a few times while writing new data increases the odds that MOS 74 # metadata for some of the txgs will survive 75 log_must sync_some_data_a_few_times $TESTPOOL1 76 typeset txg 77 txg=$(get_last_txg_synced $TESTPOOL1) 78 log_must zfs snapshot -r $TESTPOOL1@snap1 79 80 # 81 # Perform config change operations 82 # 83 if [[ -n $addvdevs ]]; then 84 log_must zpool add -f $TESTPOOL1 $addvdevs 85 fi 86 if [[ -n $attachargs ]]; then 87 log_must zpool attach $TESTPOOL1 $attachargs 88 fi 89 if [[ -n $detachvdev ]]; then 90 log_must zpool detach $TESTPOOL1 $detachvdev 91 fi 92 if [[ -n $removevdev ]]; then 93 [[ -z $finalpool ]] && 94 log_fail "Must provide final pool status!" 95 log_must zpool remove $TESTPOOL1 $removevdev 96 log_must wait_for_pool_config $TESTPOOL1 "$finalpool" 97 fi 98 if [[ -n $pathstochange ]]; then 99 # 100 # Change device paths and re-import pool to update labels 101 # 102 zpool export $TESTPOOL1 103 for dev in $pathstochange; do 104 log_must mv $dev "${dev}_new" 105 poolcheck=$(echo "$poolcheck" | \ 106 sed "s:$dev:${dev}_new:g") 107 done 108 zpool import -d $DEVICE_DIR $TESTPOOL1 109 fi 110 111 # 112 # In an attempt to leave MOS data untouched so extreme 113 # rewind is successful during import we checkpoint the 114 # pool and hope that these MOS data are part of the 115 # checkpoint (e.g they stay around). If this goes as 116 # expected, then extreme rewind should rewind back even 117 # further than the time that we took the checkpoint. 118 # 119 # Note that, ideally we would want to take a checkpoint 120 # right after we record the txg we plan to rewind to. 121 # But since we can't attach, detach or remove devices 122 # while having a checkpoint, we take it after the 123 # operation that changes the config. 124 # 125 # However, it is possible the MOS data was overwritten 126 # in which case the pool will either be unimportable, or 127 # may have been rewound prior to the data being written. 128 # In which case an error is returned and test_common() 129 # is retried by the caller to minimize false positives. 130 # 131 log_must zpool checkpoint $TESTPOOL1 132 133 log_must overwrite_data $TESTPOOL1 "" 134 135 log_must zpool export $TESTPOOL1 136 137 if zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1; then 138 verify_data_hashsums $MD5FILE && retval=0 139 140 log_must check_pool_config $TESTPOOL1 "$poolcheck" 141 log_must zpool destroy $TESTPOOL1 142 fi 143 144 # Cleanup 145 if [[ -n $pathstochange ]]; then 146 for dev in $pathstochange; do 147 log_must mv "${dev}_new" $dev 148 done 149 fi 150 # Fast way to clear vdev labels 151 log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4 152 log_must zpool destroy $TESTPOOL2 153 154 log_note "" 155 return $retval 156} 157 158function test_add_vdevs 159{ 160 typeset poolcreate="$1" 161 typeset addvdevs="$2" 162 163 log_note "$0: pool '$poolcreate', add $addvdevs." 164 165 for retry in $(seq 1 5); do 166 test_common "$poolcreate" "$addvdevs" && return 167 log_note "Retry $retry / 5 for test_add_vdevs()" 168 done 169 170 log_fail "Exhausted all 5 retries for test_add_vdevs()" 171} 172 173function test_attach_vdev 174{ 175 typeset poolcreate="$1" 176 typeset attachto="$2" 177 typeset attachvdev="$3" 178 179 log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto." 180 181 for retry in $(seq 1 5); do 182 test_common "$poolcreate" "" "$attachto $attachvdev" && return 183 log_note "Retry $retry / 5 for test_attach_vdev()" 184 done 185 186 log_fail "Exhausted all 5 retries for test_attach_vdev()" 187} 188 189function test_detach_vdev 190{ 191 typeset poolcreate="$1" 192 typeset detachvdev="$2" 193 194 log_note "$0: pool '$poolcreate', detach $detachvdev." 195 196 for retry in $(seq 1 5); do 197 test_common "$poolcreate" "" "" "$detachvdev" && return 198 log_note "Retry $retry / 5 for test_detach_vdev()" 199 done 200 201 log_fail "Exhausted all 5 retries for test_detach_vdev()" 202} 203 204function test_attach_detach_vdev 205{ 206 typeset poolcreate="$1" 207 typeset attachto="$2" 208 typeset attachvdev="$3" 209 typeset detachvdev="$4" 210 211 log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto," \ 212 "then detach $detachvdev." 213 214 for retry in $(seq 1 5); do 215 test_common "$poolcreate" "" "$attachto $attachvdev" \ 216 "$detachvdev" && return 217 log_note "Retry $retry / 5 for test_attach_detach_vdev()" 218 done 219 220 log_fail "Exhausted all 5 retries for test_attach_detach_vdev()" 221} 222 223function test_remove_vdev 224{ 225 typeset poolcreate="$1" 226 typeset removevdev="$2" 227 typeset finalpool="$3" 228 229 log_note "$0: pool '$poolcreate', remove $removevdev." 230 231 for retry in $(seq 1 5); do 232 test_common "$poolcreate" "" "" "" "$removevdev" \ 233 "$finalpool" && return 234 log_note "Retry $retry / 5 for test_remove_vdev()" 235 done 236 237 log_fail "Exhausted all 5 retries for test_remove_vdev()" 238} 239 240# Record txg history 241is_linux && log_must set_tunable32 TXG_HISTORY 100 242 243# Make the devices bigger to reduce chances of overwriting MOS metadata. 244increase_device_sizes $(( FILE_SIZE * 4 )) 245 246# Increase the number of metaslabs for small pools temporarily to 247# reduce the chance of reusing a metaslab that holds old MOS metadata. 248log_must set_tunable64 VDEV_MIN_MS_COUNT 150 249 250# Part of the rewind test is to see how it reacts to path changes 251typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3" 252 253log_note " == test rewind after device addition == " 254 255test_add_vdevs "$VDEV0" "$VDEV1" 256test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2" 257test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2" 258test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3" 259test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3" 260test_add_vdevs "$VDEV0" "draid $VDEV1 $VDEV2 $VDEV3" 261test_add_vdevs "$VDEV0" "log $VDEV1" 262test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2" 263 264log_note " == test rewind after device attach == " 265 266test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV1" 267test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV2" 268test_attach_vdev "$VDEV0 $VDEV1" "$VDEV0" "$VDEV2" 269 270log_note " == test rewind after device removal == " 271 272# Once we remove a device it will be overlooked in the device scan, so we must 273# preserve its original path 274pathstochange="$VDEV0 $VDEV2" 275test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2" 276 277# 278# Path change and detach are incompatible. Detach changes the guid of the vdev 279# so we have no direct way to link the new path to an existing vdev. 280# 281pathstochange="" 282 283log_note " == test rewind after device detach == " 284 285test_detach_vdev "mirror $VDEV0 $VDEV1" "$VDEV1" 286test_detach_vdev "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" "$VDEV1" 287test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV2" "$VDEV2" 288 289log_note " == test rewind after device attach followed by device detach == " 290 291# 292# We need to disable vdev validation since once we detach VDEV1, VDEV0 will 293# inherit the mirror tvd's guid and lose its original guid. 294# 295set_vdev_validate_skip 1 296test_attach_detach_vdev "$VDEV0" "$VDEV0" "$VDEV1" "$VDEV1" 297set_vdev_validate_skip 0 298 299log_pass "zpool import rewind after configuration change passed." 300