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