diff options
Diffstat (limited to 'usr/src/test/zfs-tests')
20 files changed, 1675 insertions, 15 deletions
diff --git a/usr/src/test/zfs-tests/runfiles/delphix.run b/usr/src/test/zfs-tests/runfiles/delphix.run index 88d6e368ab..9c59485b2a 100644 --- a/usr/src/test/zfs-tests/runfiles/delphix.run +++ b/usr/src/test/zfs-tests/runfiles/delphix.run @@ -279,7 +279,17 @@ tests = ['zpool_import_001_pos', 'zpool_import_002_pos', 'zpool_import_features_001_pos', 'zpool_import_features_002_neg', 'zpool_import_features_003_pos', 'zpool_import_missing_001_pos', 'zpool_import_missing_002_pos', 'zpool_import_missing_003_pos', - 'zpool_import_rename_001_pos'] + 'zpool_import_rename_001_pos', + 'import_cachefile_device_added', + 'import_cachefile_device_removed', + 'import_cachefile_mirror_attached', + 'import_cachefile_mirror_detached', + 'import_cachefile_device_replaced', + 'import_rewind_config_changed', + 'import_rewind_device_replaced', + 'import_cachefile_shared_device', + 'import_paths_changed', + 'import_devices_missing'] [/opt/zfs-tests/tests/functional/cli_root/zpool_labelclear] tests = ['zpool_labelclear_active', 'zpool_labelclear_exported'] diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh new file mode 100644 index 0000000000..bda6b891b9 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_added.ksh @@ -0,0 +1,76 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable using an outdated cachefile that is unaware +# that one or two top-level vdevs were added. +# +# STRATEGY: +# 1. Create a pool with some devices and an alternate cachefile. +# 2. Backup the cachefile. +# 3. Add a device/mirror/raid to the pool. +# 4. Export the pool. +# 5. Verify that we can import the pool using the backed-up cachefile. +# + +verify_runnable "global" + +log_onexit cleanup + +function test_add_vdevs +{ + typeset poolcreate="$1" + typeset addvdevs="$2" + typeset poolcheck="$3" + + log_note "$0: pool '$poolcreate', add $addvdevs." + + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate + + log_must cp $CPATH $CPATHBKP + + log_must zpool add -f $TESTPOOL1 $addvdevs + + log_must zpool export $TESTPOOL1 + + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcheck" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP + + log_note "" +} + +test_add_vdevs "$VDEV0" "$VDEV1" "$VDEV0 $VDEV1" +test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2" "$VDEV0 $VDEV1 $VDEV2" +test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2" +test_add_vdevs "$VDEV0" "mirror $VDEV1 $VDEV2" \ + "$VDEV0 mirror $VDEV1 $VDEV2" +test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3" \ + "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" +test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3" \ + "$VDEV0 raidz $VDEV1 $VDEV2 $VDEV3" +test_add_vdevs "$VDEV0" "log $VDEV1" "$VDEV0 log $VDEV1" +test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2" "$VDEV0 $VDEV2 log $VDEV1" +test_add_vdevs "$VDEV0" "$VDEV1 log $VDEV2" "$VDEV0 $VDEV1 log $VDEV2" + +log_pass "zpool import -c cachefile_unaware_of_add passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh new file mode 100644 index 0000000000..1d878b7a25 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_removed.ksh @@ -0,0 +1,145 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable using an outdated cachefile that is unaware +# that one or more vdevs were removed. +# +# STRATEGY: +# 1. Create a pool with some devices and an alternate cachefile. +# 2. Backup the cachefile. +# 3. Remove device(s) from the pool and remove them. +# 4. (Optionally) Add device(s) to pool. +# 5. Export the pool. +# 6. Verify that we can import the pool using the backed-up cachefile. +# + +verify_runnable "global" + +function custom_cleanup +{ + cleanup +} + +log_onexit custom_cleanup + +function test_remove_vdev +{ + typeset poolcreate="$1" + typeset removevdev="$2" + typeset poolcheck="$3" + + log_note "$0: pool '$poolcreate', remove $2." + + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate + + log_must cp $CPATH $CPATHBKP + + log_must zpool remove $TESTPOOL1 $removevdev + log_must wait_for_pool_config $TESTPOOL1 "$poolcheck" + log_must rm $removevdev + + log_must zpool export $TESTPOOL1 + + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcheck" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP + log_must mkfile $FILE_SIZE $removevdev + + log_note "" +} + +# +# We have to remove top-level non-log vdevs one by one, else there is a high +# chance pool will report busy and command will fail for the second vdev. +# +function test_remove_two_vdevs +{ + log_note "$0." + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 \ + $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4 + + log_must cp $CPATH $CPATHBKP + + log_must zpool remove $TESTPOOL1 $VDEV4 + log_must wait_for_pool_config $TESTPOOL1 \ + "$VDEV0 $VDEV1 $VDEV2 $VDEV3" + log_must zpool remove $TESTPOOL1 $VDEV3 + log_must wait_for_pool_config $TESTPOOL1 "$VDEV0 $VDEV1 $VDEV2" + log_must rm $VDEV3 $VDEV4 + + log_must zpool export $TESTPOOL1 + + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$VDEV0 $VDEV1 $VDEV2" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP + log_must mkfile $FILE_SIZE $VDEV3 $VDEV4 + + log_note "" +} + +# +# We want to test the case where a whole created by a log device is filled +# by a regular device +# +function test_remove_log_then_add_vdev +{ + log_note "$0." + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 \ + $VDEV0 $VDEV1 $VDEV2 log $VDEV3 + + log_must cp $CPATH $CPATHBKP + + log_must zpool remove $TESTPOOL1 $VDEV1 + log_must wait_for_pool_config $TESTPOOL1 "$VDEV0 $VDEV2 log $VDEV3" + log_must zpool remove $TESTPOOL1 $VDEV3 + log_must check_pool_config $TESTPOOL1 "$VDEV0 $VDEV2" + log_must rm $VDEV1 $VDEV3 + log_must zpool add $TESTPOOL1 $VDEV4 + + log_must zpool export $TESTPOOL1 + + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$VDEV0 $VDEV2 $VDEV4" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP + log_must mkfile $FILE_SIZE $VDEV1 $VDEV3 + + log_note "" +} + +test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV2" "$VDEV0 $VDEV1" +test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2" +test_remove_vdev "$VDEV0 log $VDEV1" "$VDEV1" "$VDEV0" +test_remove_vdev "$VDEV0 log $VDEV1 $VDEV2" "$VDEV1 $VDEV2" "$VDEV0" +test_remove_vdev "$VDEV0 $VDEV1 $VDEV2 log $VDEV3" "$VDEV2" \ + "$VDEV0 $VDEV1 log $VDEV3" +test_remove_two_vdevs +test_remove_log_then_add_vdev + +log_pass "zpool import -c cachefile_unaware_of_remove passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh new file mode 100644 index 0000000000..74957770cb --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_device_replaced.ksh @@ -0,0 +1,164 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable using an outdated cachefile that is unaware +# of a zpool replace operation at different stages in time. +# +# STRATEGY: +# 1. Create a pool with some devices and an alternate cachefile. +# 2. Backup the cachefile. +# 3. Initiate device replacement, backup cachefile again and export pool. +# Special care must be taken so that resilvering doesn't complete +# before we exported the pool. +# 4. Verify that we can import the pool using the first cachefile backup. +# (Test 1. cachefile: pre-replace, pool: resilvering) +# 5. Wait for the resilvering to finish and export the pool. +# 6. Verify that we can import the pool using the first cachefile backup. +# (Test 2. cachefile: pre-replace, pool: post-replace) +# 7. Export the pool. +# 8. Verify that we can import the pool using the second cachefile backup. +# (Test 3. cachefile: resilvering, pool: post-replace) +# +# STRATEGY TO SLOW DOWN RESILVERING: +# 1. Reduce zfs_txg_timeout, which controls how long can we resilver for +# each sync. +# 2. Add data to pool +# 3. Re-import the pool so that data isn't cached +# 4. Use zinject to slow down device I/O +# 5. Trigger the resilvering +# 6. Use spa freeze to stop writing to the pool. +# 7. Clear zinject events (needed to export the pool) +# 8. Export the pool +# + +verify_runnable "global" + +ZFS_TXG_TIMEOUT="" + +function custom_cleanup +{ + # Revert zfs_txg_timeout to defaults + [[ -n ZFS_TXG_TIMEOUT ]] && + log_must set_zfs_txg_timeout $ZFS_TXG_TIMEOUT + + cleanup +} + +log_onexit custom_cleanup + +function test_replacing_vdevs +{ + typeset poolcreate="$1" + typeset replacevdev="$2" + typeset replaceby="$3" + typeset poolfinalstate="$4" + typeset zinjectdevices="$5" + typeset earlyremove="$6" + + log_note "$0: pool '$poolcreate', replace $replacevdev by $replaceby." + + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate + + # Cachefile: pool in pre-replace state + log_must cp $CPATH $CPATHBKP + + # Steps to insure resilvering happens very slowly. + log_must write_some_data $TESTPOOL1 + log_must zpool export $TESTPOOL1 + log_must cp $CPATHBKP $CPATH + log_must zpool import -c $CPATH -o cachefile=$CPATH $TESTPOOL1 + typeset device + for device in $zinjectdevices ; do + log_must zinject -d $device -D 200:1 $TESTPOOL1 > /dev/null + done + log_must zpool replace $TESTPOOL1 $replacevdev $replaceby + + # Cachefile: pool in resilvering state + log_must cp $CPATH $CPATHBKP2 + + # We must disable zinject in order to export the pool, so we freeze + # it first to prevent writing out subsequent resilvering progress. + log_must zpool freeze $TESTPOOL1 + # Confirm pool is still replacing + log_must pool_is_replacing $TESTPOOL1 + log_must zinject -c all > /dev/null + log_must zpool export $TESTPOOL1 + + ( $earlyremove ) && log_must rm $replacevdev + + ############################################################ + # Test 1. Cachefile: pre-replace, pool: resilvering + ############################################################ + log_must cp $CPATHBKP $CPATH + log_must zpool import -c $CPATH $TESTPOOL1 + + # Wait for resilvering to finish + log_must wait_for_pool_config $TESTPOOL1 "$poolfinalstate" + log_must zpool export $TESTPOOL1 + + ( ! $earlyremove ) && log_must rm $replacevdev + + ############################################################ + # Test 2. Cachefile: pre-replace, pool: post-replace + ############################################################ + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolfinalstate" + log_must zpool export $TESTPOOL1 + + ############################################################ + # Test 3. Cachefile: resilvering, pool: post-replace + ############################################################ + log_must zpool import -c $CPATHBKP2 $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolfinalstate" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP $CPATHBKP2 + log_must mkfile $FILE_SIZE $replacevdev + + log_note "" +} + +# We set zfs_txg_timeout to 1 to reduce resilvering time at each sync. +ZFS_TXG_TIMEOUT=$(get_zfs_txg_timeout) +set_zfs_txg_timeout 1 + +test_replacing_vdevs "$VDEV0 $VDEV1" \ + "$VDEV1" "$VDEV2" \ + "$VDEV0 $VDEV2" \ + "$VDEV0 $VDEV1" \ + false + +test_replacing_vdevs "mirror $VDEV0 $VDEV1" \ + "$VDEV1" "$VDEV2" \ + "mirror $VDEV0 $VDEV2" \ + "$VDEV0 $VDEV1" \ + true + +test_replacing_vdevs "raidz $VDEV0 $VDEV1 $VDEV2" \ + "$VDEV1" "$VDEV3" \ + "raidz $VDEV0 $VDEV3 $VDEV2" \ + "$VDEV0 $VDEV1 $VDEV2" \ + true + +set_zfs_txg_timeout $ZFS_TXG_TIMEOUT + +log_pass "zpool import -c cachefile_unaware_of_replace passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh new file mode 100644 index 0000000000..987b745b91 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_attached.ksh @@ -0,0 +1,72 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable using an outdated cachefile that misses a +# mirror that was attached. +# +# STRATEGY: +# 1. Create a pool with some devices and an alternate cachefile. +# 2. Backup the cachefile. +# 3. Attach a mirror to one of the devices in the pool. +# 4. Export the pool. +# 5. Verify that we can import the pool using the backed-up cachefile. +# + +verify_runnable "global" + +log_onexit cleanup + +function test_attach_vdev +{ + typeset poolcreate="$1" + typeset attachto="$2" + typeset attachvdev="$3" + typeset poolcheck="$4" + + log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto." + + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate + + log_must cp $CPATH $CPATHBKP + + log_must zpool attach $TESTPOOL1 $attachto $attachvdev + + log_must zpool export $TESTPOOL1 + + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcheck" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP + + log_note "" +} + +test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV4" "mirror $VDEV0 $VDEV4" +test_attach_vdev "$VDEV0 $VDEV1" "$VDEV1" "$VDEV4" \ + "$VDEV0 mirror $VDEV1 $VDEV4" +test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV4" \ + "mirror $VDEV0 $VDEV1 $VDEV4" +test_attach_vdev "$VDEV0 log $VDEV1" "$VDEV1" "$VDEV4" \ + "$VDEV0 log mirror $VDEV1 $VDEV4" + +log_pass "zpool import -c cachefile_unaware_of_attach passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh new file mode 100644 index 0000000000..85ec51673b --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_mirror_detached.ksh @@ -0,0 +1,70 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable using an outdated cachefile that is unaware +# that a mirror was detached. +# +# STRATEGY: +# 1. Create a pool with some devices mirrored and an alternate cachefile. +# 2. Backup the cachefile. +# 3. Detach a mirror from the pool. +# 4. Export the pool. +# 5. Verify that we can import the pool using the backed-up cachefile. +# + +verify_runnable "global" + +log_onexit cleanup + +function test_detach_vdev +{ + typeset poolcreate="$1" + typeset poolcheck="$2" + + log_note "$0: pool '$poolcreate', detach $VDEV4." + + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate + + log_must cp $CPATH $CPATHBKP + + log_must zpool detach $TESTPOOL1 $VDEV4 + log_must rm -f $VDEV4 + + log_must zpool export $TESTPOOL1 + + log_must zpool import -c $CPATHBKP $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcheck" + + # Cleanup + log_must zpool destroy $TESTPOOL1 + log_must rm -f $CPATH $CPATHBKP + log_must mkfile $FILE_SIZE $VDEV4 + + log_note "" +} + +test_detach_vdev "mirror $VDEV0 $VDEV4" "$VDEV0" +test_detach_vdev "mirror $VDEV0 $VDEV4 mirror $VDEV1 $VDEV2" \ + "$VDEV0 mirror $VDEV1 $VDEV2" +test_detach_vdev "mirror $VDEV0 $VDEV1 $VDEV4" "mirror $VDEV0 $VDEV1" +test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV4" "$VDEV0 log $VDEV1" + +log_pass "zpool import -c cachefile_unaware_of_detach passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh new file mode 100644 index 0000000000..66225c11b9 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_cachefile_shared_device.ksh @@ -0,0 +1,113 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should not try to write to a device that doesn't belong to it +# anymore, even if the device is in its cachefile. +# +# STRATEGY: +# 1. Create pool1 with some devices and an alternate cachefile. +# 2. Backup the cachefile. +# 3. Export pool1. +# 4. Create pool2 using a device that belongs to pool1. +# 5. Export pool2. +# 6. Compute checksum of the shared device. +# 7. Import pool1 and write some data to it. +# 8. Verify that the checksum of the shared device hasn't changed. +# + +verify_runnable "global" + +function custom_cleanup +{ + destroy_pool $TESTPOOL2 + cleanup +} + +log_onexit custom_cleanup + +function dev_checksum +{ + typeset dev="$1" + typeset checksum + + log_note "Compute checksum of '$dev'" + + checksum=$(md5sum $dev) + if [[ $? -ne 0 ]]; then + log_fail "Failed to compute checksum of '$dev'" + return 1 + fi + + echo "$checksum" + return 0 +} + +function test_shared_device +{ + typeset pool1="$1" + typeset pool2="$2" + typeset sharedvdev="$3" + typeset importflags="${4:-}" + + log_note "$0: pool1 '$pool1', pool2 '$pool2' takes $sharedvdev." + + log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $pool1 + + log_must cp $CPATH $CPATHBKP + + log_must zpool export $TESTPOOL1 + + log_must zpool create -f $TESTPOOL2 $pool2 + + log_must zpool export $TESTPOOL2 + + typeset checksum1=$(dev_checksum $sharedvdev) + + log_must zpool import -c $CPATHBKP $importflags $TESTPOOL1 + + log_must write_some_data $TESTPOOL1 2 + + log_must zpool destroy $TESTPOOL1 + + typeset checksum2=$(dev_checksum $sharedvdev) + + if [[ $checksum1 == $checksum2 ]]; then + log_pos "Device hasn't been modified by original pool" + else + log_fail "Device has been modified by original pool." \ + "Checksum mismatch: $checksum1 != $checksum2." + fi + + # Cleanup + log_must zpool import -d $DEVICE_DIR $TESTPOOL2 + log_must zpool destroy $TESTPOOL2 + log_must rm -f $CPATH $CPATHBKP + + log_note "" +} + +test_shared_device "mirror $VDEV0 $VDEV1" "mirror $VDEV1 $VDEV2" "$VDEV1" +test_shared_device "mirror $VDEV0 $VDEV1 $VDEV2" "mirror $VDEV2 $VDEV3" \ + "$VDEV2" +test_shared_device "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV2" "$VDEV2" +test_shared_device "$VDEV0 log $VDEV1" "$VDEV2 log $VDEV1" "$VDEV1" "-m" + +log_pass "Pool doesn't write to a device it doesn't own anymore." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh new file mode 100644 index 0000000000..3f45ada6ee --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_devices_missing.ksh @@ -0,0 +1,122 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable when up to 2 top-level devices are missing. +# +# STRATEGY: +# 1. Create a pool. +# 2. Write some data to the pool and checksum it. +# 3. Add one or more devices. +# 4. Write more data to the pool and checksum it. +# 5. Export the pool. +# 6. Move added devices out of the devices directory. +# 7. Import the pool with missing devices. +# 8. Verify that the first batch of data is intact. +# 9. Verify that accessing the second batch of data doesn't suspend pool. +# 10. Export the pool, move back missing devices, Re-import the pool. +# 11. Verify that all the data is intact. +# + +verify_runnable "global" + +function custom_cleanup +{ + log_must set_spa_load_verify_metadata 1 + log_must set_spa_load_verify_data 1 + log_must set_zfs_max_missing_tvds 0 + log_must rm -rf $BACKUP_DEVICE_DIR + # Highly damaged pools may fail to be destroyed, so we export them. + poolexists $TESTPOOL1 && log_must zpool export $TESTPOOL1 + cleanup +} + +log_onexit custom_cleanup + +function test_devices_missing +{ + typeset poolcreate="$1" + typeset addvdevs="$2" + typeset missingvdevs="$3" + typeset -i missingtvds="$4" + + log_note "$0: pool '$poolcreate', adding $addvdevs, then" \ + "moving away $missingvdevs." + + log_must zpool create $TESTPOOL1 $poolcreate + + log_must generate_data $TESTPOOL1 $MD5FILE "first" + + log_must zpool add $TESTPOOL1 $addvdevs + + log_must generate_data $TESTPOOL1 $MD5FILE2 "second" + + log_must zpool export $TESTPOOL1 + + log_must mv $missingvdevs $BACKUP_DEVICE_DIR + + # Tell zfs that it is ok to import a pool with missing top-level vdevs + log_must set_zfs_max_missing_tvds $missingtvds + # Missing devices means that data or metadata may be corrupted. + (( missingtvds > 1 )) && log_must set_spa_load_verify_metadata 0 + log_must set_spa_load_verify_data 0 + log_must zpool import -o readonly=on -d $DEVICE_DIR $TESTPOOL1 + + log_must verify_data_md5sums $MD5FILE + + log_note "Try reading second batch of data, make sure pool doesn't" \ + "get suspended." + verify_data_md5sums $MD5FILE >/dev/null 2>&1 + + log_must zpool export $TESTPOOL1 + + typeset newpaths=$(echo "$missingvdevs" | \ + sed "s:$DEVICE_DIR:$BACKUP_DEVICE_DIR:g") + log_must mv $newpaths $DEVICE_DIR + log_must set_spa_load_verify_metadata 1 + log_must set_spa_load_verify_data 1 + log_must set_zfs_max_missing_tvds 0 + log_must zpool import -d $DEVICE_DIR $TESTPOOL1 + + log_must verify_data_md5sums $MD5FILE + log_must verify_data_md5sums $MD5FILE2 + + # Cleanup + log_must zpool destroy $TESTPOOL1 + + log_note "" +} + +log_must mkdir $BACKUP_DEVICE_DIR + +test_devices_missing "$VDEV0" "$VDEV1" "$VDEV1" 1 +test_devices_missing "$VDEV0" "$VDEV1 $VDEV2" "$VDEV1" 1 +test_devices_missing "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3" \ + "$VDEV2 $VDEV3" 1 +test_devices_missing "$VDEV0 log $VDEV1" "$VDEV2" "$VDEV2" 1 + +# +# Note that we are testing for 2 non-consecutive missing devices. +# Missing consecutive devices results in missing metadata. Because of +# Missing metadata can cause the root dataset to fail to mount. +# +test_devices_missing "$VDEV0" "$VDEV1 $VDEV2 $VDEV3" "$VDEV1 $VDEV3" 2 + +log_pass "zpool import succeeded with missing devices." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh new file mode 100644 index 0000000000..457eb6a14a --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_paths_changed.ksh @@ -0,0 +1,98 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# A pool should be importable even if device paths have changed. +# +# STRATEGY: +# 1. Create a pool. +# 2. Export the pool. +# 3. Change the paths of some of the devices. +# 4. Verify that we can import the pool in a healthy state. +# + +verify_runnable "global" + +log_onexit cleanup + +function test_new_paths +{ + typeset poolcreate="$1" + typeset pathstochange="$2" + + log_note "$0: pool '$poolcreate', changing paths of $pathstochange." + + log_must zpool create $TESTPOOL1 $poolcreate + + log_must zpool export $TESTPOOL1 + + for dev in $pathstochange; do + log_must mv $dev "${dev}_new" + done + + log_must zpool import -d $DEVICE_DIR $TESTPOOL1 + log_must check_pool_healthy $TESTPOOL1 + + # Cleanup + log_must zpool destroy $TESTPOOL1 + for dev in $pathstochange; do + log_must mv "${dev}_new" $dev + done + + log_note "" +} + +function test_swap_paths +{ + typeset poolcreate="$1" + typeset pathtoswap1="$2" + typeset pathtoswap2="$3" + + log_note "$0: pool '$poolcreate', swapping paths of $pathtoswap1" \ + "and $pathtoswap2." + + log_must zpool create $TESTPOOL1 $poolcreate + + log_must zpool export $TESTPOOL1 + + log_must mv $pathtoswap2 "$pathtoswap2.tmp" + log_must mv $pathtoswap1 "$pathtoswap2" + log_must mv "$pathtoswap2.tmp" $pathtoswap1 + + log_must zpool import -d $DEVICE_DIR $TESTPOOL1 + log_must check_pool_healthy $TESTPOOL1 + + # Cleanup + log_must zpool destroy $TESTPOOL1 + + log_note "" +} + +test_new_paths "$VDEV0 $VDEV1" "$VDEV0 $VDEV1" +test_new_paths "mirror $VDEV0 $VDEV1" "$VDEV0 $VDEV1" +test_new_paths "$VDEV0 log $VDEV1" "$VDEV1" +test_new_paths "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV1" + +test_swap_paths "$VDEV0 $VDEV1" "$VDEV0" "$VDEV1" +test_swap_paths "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV0" "$VDEV1" +test_swap_paths "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" \ + "$VDEV0" "$VDEV2" + +log_pass "zpool import succeeded after changing device paths." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh new file mode 100644 index 0000000000..dda30a09df --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_config_changed.ksh @@ -0,0 +1,236 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# It should be possible to rewind a pool beyond a configuration change. +# +# STRATEGY: +# 1. Create a pool. +# 2. Generate files and remember their md5sum. +# 3. Note last synced txg. +# 4. Take a snapshot to make sure old blocks are not overwritten. +# 5. Perform zpool add/attach/detach/remove operation. +# 6. Change device paths if requested and re-import pool. +# 7. Overwrite the files. +# 8. Export the pool. +# 9. Verify that we can rewind the pool to the noted txg. +# 10. Verify that the files are readable and retain their old data. +# +# DISCLAIMER: +# This test can fail since nothing guarantees that old MOS blocks aren't +# overwritten. Snapshots protect datasets and data files but not the MOS. +# sync_some_data_a_few_times interleaves file data and MOS data for a few +# txgs, thus increasing the odds that some txgs will have their MOS data +# left untouched. +# + +verify_runnable "global" + +function custom_cleanup +{ + set_vdev_validate_skip 0 + cleanup +} + +log_onexit custom_cleanup + +function test_common +{ + typeset poolcreate="$1" + typeset addvdevs="$2" + typeset attachargs="${3:-}" + typeset detachvdev="${4:-}" + typeset removevdev="${5:-}" + typeset finalpool="${6:-}" + + typeset poolcheck="$poolcreate" + + log_must zpool create $TESTPOOL1 $poolcreate + + log_must generate_data $TESTPOOL1 $MD5FILE + + # syncing a few times while writing new data increases the odds that MOS + # metadata for some of the txgs will survive + log_must sync_some_data_a_few_times $TESTPOOL1 + typeset txg + txg=$(get_last_txg_synced $TESTPOOL1) + log_must zfs snapshot -r $TESTPOOL1@snap1 + + # + # Perform config change operations + # + if [[ -n $addvdev ]]; then + log_must zpool add -f $TESTPOOL1 $addvdev + fi + if [[ -n $attachargs ]]; then + log_must zpool attach $TESTPOOL1 $attachargs + fi + if [[ -n $detachvdev ]]; then + log_must zpool detach $TESTPOOL1 $detachvdev + fi + if [[ -n $removevdev ]]; then + [[ -z $finalpool ]] && + log_fail "Must provide final pool status!" + log_must zpool remove $TESTPOOL1 $removevdev + log_must wait_for_pool_config $TESTPOOL1 "$finalpool" + fi + if [[ -n $pathstochange ]]; then + # + # Change device paths and re-import pool to update labels + # + sudo zpool export $TESTPOOL1 + for dev in $pathstochange; do + log_must mv $dev "${dev}_new" + poolcheck=$(echo "$poolcheck" | \ + sed "s:$dev:${dev}_new:g") + done + sudo zpool import -d $DEVICE_DIR $TESTPOOL1 + fi + + log_must overwrite_data $TESTPOOL1 "" + + log_must zpool export $TESTPOOL1 + + log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcheck" + + log_must verify_data_md5sums $MD5FILE + + # Cleanup + log_must zpool destroy $TESTPOOL1 + if [[ -n $pathstochange ]]; then + for dev in $pathstochange; do + log_must mv "${dev}_new" $dev + done + fi + # Fast way to clear vdev labels + log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4 + log_must zpool destroy $TESTPOOL2 + + log_note "" +} + +function test_add_vdevs +{ + typeset poolcreate="$1" + typeset addvdevs="$2" + + log_note "$0: pool '$poolcreate', add $addvdevs." + + test_common "$poolcreate" "$addvdevs" +} + +function test_attach_vdev +{ + typeset poolcreate="$1" + typeset attachto="$2" + typeset attachvdev="$3" + + log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto." + + test_common "$poolcreate" "" "$attachto $attachvdev" +} + +function test_detach_vdev +{ + typeset poolcreate="$1" + typeset detachvdev="$2" + + log_note "$0: pool '$poolcreate', detach $detachvdev." + + test_common "$poolcreate" "" "" "$detachvdev" +} + +function test_attach_detach_vdev +{ + typeset poolcreate="$1" + typeset attachto="$2" + typeset attachvdev="$3" + typeset detachvdev="$4" + + log_note "$0: pool '$poolcreate', attach $attachvdev to $attachto," \ + "then detach $detachvdev." + + test_common "$poolcreate" "" "$attachto $attachvdev" "$detachvdev" +} + +function test_remove_vdev +{ + typeset poolcreate="$1" + typeset removevdev="$2" + typeset finalpool="$3" + + log_note "$0: pool '$poolcreate', remove $removevdev." + + test_common "$poolcreate" "" "" "" "$removevdev" "$finalpool" +} + +# Make the devices bigger to reduce chances of overwriting MOS metadata. +increase_device_sizes $(( FILE_SIZE * 4 )) + +# Part of the rewind test is to see how it reacts to path changes +typeset pathstochange="$VDEV0 $VDEV1 $VDEV2 $VDEV3" + +log_note " == test rewind after device addition == " + +test_add_vdevs "$VDEV0" "$VDEV1" +test_add_vdevs "$VDEV0 $VDEV1" "$VDEV2" +test_add_vdevs "$VDEV0" "$VDEV1 $VDEV2" +test_add_vdevs "mirror $VDEV0 $VDEV1" "mirror $VDEV2 $VDEV3" +test_add_vdevs "$VDEV0" "raidz $VDEV1 $VDEV2 $VDEV3" +test_add_vdevs "$VDEV0" "log $VDEV1" +test_add_vdevs "$VDEV0 log $VDEV1" "$VDEV2" + +log_note " == test rewind after device attach == " + +test_attach_vdev "$VDEV0" "$VDEV0" "$VDEV1" +test_attach_vdev "mirror $VDEV0 $VDEV1" "$VDEV0" "$VDEV2" +test_attach_vdev "$VDEV0 $VDEV1" "$VDEV0" "$VDEV2" + +log_note " == test rewind after device removal == " + +# Once we remove a device it will be overlooked in the device scan, so we must +# preserve its original path +pathstochange="$VDEV0 $VDEV2" +test_remove_vdev "$VDEV0 $VDEV1 $VDEV2" "$VDEV1" "$VDEV0 $VDEV2" + +# +# Path change and detach are incompatible. Detach changes the guid of the vdev +# so we have no direct way to link the new path to an existing vdev. +# +pathstochange="" + +log_note " == test rewind after device detach == " + +test_detach_vdev "mirror $VDEV0 $VDEV1" "$VDEV1" +test_detach_vdev "mirror $VDEV0 $VDEV1 mirror $VDEV2 $VDEV3" "$VDEV1" +test_detach_vdev "$VDEV0 log mirror $VDEV1 $VDEV2" "$VDEV2" + +log_note " == test rewind after device attach followed by device detach == " + +# +# We need to disable vdev validation since once we detach VDEV1, VDEV0 will +# inherit the mirror tvd's guid and lose its original guid. +# +set_vdev_validate_skip 1 +test_attach_detach_vdev "$VDEV0" "$VDEV0" "$VDEV1" "$VDEV1" +set_vdev_validate_skip 0 + +log_pass "zpool import rewind after configuration change passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh new file mode 100644 index 0000000000..d57ced1040 --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/import_rewind_device_replaced.ksh @@ -0,0 +1,181 @@ +#!/usr/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib + +# +# DESCRIPTION: +# It should be possible to rewind a pool beyond a device replacement. +# +# STRATEGY: +# 1. Create a pool. +# 2. Generate files and remember their md5sum. +# 3. Sync a few times and note last synced txg. +# 4. Take a snapshot to make sure old blocks are not overwritten. +# 5. Initiate device replacement and export the pool. Special care must +# be taken so that resilvering doesn't complete before the export. +# 6. Test 1: Rewind pool to noted txg and then verify data checksums. +# Import it read-only so that we do not overwrite blocks in later txgs. +# 7. Re-import pool at latest txg and let the replacement finish. +# 8. Export the pool an remove the new device - we shouldn't need it. +# 9. Test 2: Rewind pool to noted txg and then verify data checksums. +# +# STRATEGY TO SLOW DOWN RESILVERING: +# 1. Reduce zfs_txg_timeout, which controls how long can we resilver for +# each sync. +# 2. Add data to pool +# 3. Re-import the pool so that data isn't cached +# 4. Use zinject to slow down device I/O +# 5. Trigger the resilvering +# 6. Use spa freeze to stop writing to the pool. +# 7. Clear zinject events (needed to export the pool) +# 8. Export the pool +# +# DISCLAIMER: +# This test can fail since nothing guarantees that old MOS blocks aren't +# overwritten. Snapshots protect datasets and data files but not the MOS. +# sync_some_data_a_few_times interleaves file data and MOS data for a few +# txgs, thus increasing the odds that some txgs will have their MOS data +# left untouched. +# + +verify_runnable "global" + +ZFS_TXG_TIMEOUT="" + +function custom_cleanup +{ + # Revert zfs_txg_timeout to defaults + [[ -n ZFS_TXG_TIMEOUT ]] && + log_must set_zfs_txg_timeout $ZFS_TXG_TIMEOUT + log_must rm -rf $BACKUP_DEVICE_DIR + cleanup +} + +log_onexit custom_cleanup + +function test_replace_vdev +{ + typeset poolcreate="$1" + typeset replacevdev="$2" + typeset replaceby="$3" + typeset poolfinalstate="$4" + typeset zinjectdevices="$5" + + log_note "$0: pool '$poolcreate', replace $replacevdev by $replaceby." + + log_must zpool create $TESTPOOL1 $poolcreate + + # generate data and checksum it + log_must generate_data $TESTPOOL1 $MD5FILE + + # add more data so that resilver takes longer + log_must write_some_data $TESTPOOL1 + + # Syncing a few times while writing new data increases the odds that + # MOS metadata for some of the txgs will survive. + log_must sync_some_data_a_few_times $TESTPOOL1 + typeset txg + txg=$(get_last_txg_synced $TESTPOOL1) + log_must zfs snapshot -r $TESTPOOL1@snap1 + + # This should not free original data. + log_must overwrite_data $TESTPOOL1 "" + + # Steps to insure resilvering happens very slowly. + log_must zpool export $TESTPOOL1 + log_must zpool import -d $DEVICE_DIR $TESTPOOL1 + typeset device + for device in $zinjectdevices ; do + log_must zinject -d $device -D 200:1 $TESTPOOL1 > /dev/null + done + log_must zpool replace $TESTPOOL1 $replacevdev $replaceby + + # We must disable zinject in order to export the pool, so we freeze + # it first to prevent writing out subsequent resilvering progress. + log_must zpool freeze $TESTPOOL1 + # Confirm pool is still replacing + log_must pool_is_replacing $TESTPOOL1 + log_must zinject -c all > /dev/null + log_must zpool export $TESTPOOL1 + + ############################################################ + # Test 1: rewind while device is resilvering. + # Import read only to avoid overwriting more recent blocks. + ############################################################ + log_must zpool import -d $DEVICE_DIR -o readonly=on -T $txg $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcreate" + + log_must verify_data_md5sums $MD5FILE + + log_must zpool export $TESTPOOL1 + + # Import pool at latest txg to finish the resilvering + log_must zpool import -d $DEVICE_DIR $TESTPOOL1 + log_must overwrite_data $TESTPOOL1 "" + log_must wait_for_pool_config $TESTPOOL1 "$poolfinalstate" + log_must zpool export $TESTPOOL1 + + # Move out the new device + log_must mv $replaceby $BACKUP_DEVICE_DIR/ + + ############################################################ + # Test 2: rewind after device has been replaced. + # Import read-write since we won't need the pool anymore. + ############################################################ + log_must zpool import -d $DEVICE_DIR -T $txg $TESTPOOL1 + log_must check_pool_config $TESTPOOL1 "$poolcreate" + + log_must verify_data_md5sums $MD5FILE + + # Cleanup + log_must zpool destroy $TESTPOOL1 + # Restore the device we moved out + log_must mv "$BACKUP_DEVICE_DIR/$(basename $replaceby)" $DEVICE_DIR/ + # Fast way to clear vdev labels + log_must zpool create -f $TESTPOOL2 $VDEV0 $VDEV1 $VDEV2 $VDEV3 $VDEV4 + log_must zpool destroy $TESTPOOL2 + + log_note "" +} + +log_must mkdir $BACKUP_DEVICE_DIR +# Make the devices bigger to reduce chances of overwriting MOS metadata. +increase_device_sizes $(( FILE_SIZE * 4 )) + +# We set zfs_txg_timeout to 1 to reduce resilvering time at each sync. +ZFS_TXG_TIMEOUT=$(get_zfs_txg_timeout) +set_zfs_txg_timeout 1 + +test_replace_vdev "$VDEV0 $VDEV1" \ + "$VDEV1" "$VDEV2" \ + "$VDEV0 $VDEV2" \ + "$VDEV0 $VDEV1" + +test_replace_vdev "mirror $VDEV0 $VDEV1" \ + "$VDEV1" "$VDEV2" \ + "mirror $VDEV0 $VDEV2" \ + "$VDEV0 $VDEV1" + +test_replace_vdev "raidz $VDEV0 $VDEV1 $VDEV2" \ + "$VDEV1" "$VDEV3" \ + "raidz $VDEV0 $VDEV3 $VDEV2" \ + "$VDEV0 $VDEV1 $VDEV2" + +set_zfs_txg_timeout $ZFS_TXG_TIMEOUT + +log_pass "zpool import rewind after device replacement passed." diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg index 08cb5f63e8..193c32c8ce 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.cfg @@ -25,7 +25,7 @@ # # -# Copyright (c) 2012, 2015 by Delphix. All rights reserved. +# Copyright (c) 2012, 2016 by Delphix. All rights reserved. # . $STF_SUITE/include/libtest.shlib @@ -64,11 +64,17 @@ export SLICE_SIZE="$((MINVDEVSIZE / (1024 * 1024)))m" export MAX_NUM=5 export GROUP_NUM=3 export DEVICE_DIR=/dev_import-test -export BACKUP_DEVICE_DIR=/bakdev_import-test +export BACKUP_DEVICE_DIR=$DEVICE_DIR/backup export DEVICE_FILE=disk export DEVICE_ARCHIVE=archive_import-test export MYTESTFILE=$STF_SUITE/include/libtest.shlib +export CPATH=/var/tmp/cachefile.$$ +export CPATHBKP=/var/tmp/cachefile.$$.bkp +export CPATHBKP2=/var/tmp/cachefile.$$.bkp2 +export MD5FILE=/var/tmp/md5sums.$$ +export MD5FILE2=/var/tmp/md5sums.$$.2 + typeset -i num=0 while (( num < $GROUP_NUM )); do DEVICE_FILES="$DEVICE_FILES ${DEVICE_DIR}/${DEVICE_FILE}$num" diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib new file mode 100644 index 0000000000..04ce5f858d --- /dev/null +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import.kshlib @@ -0,0 +1,367 @@ +#!/usr/bin/ksh + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright (c) 2016 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg + +# +# Prototype cleanup function for zpool_import tests. +# +function cleanup +{ + destroy_pool $TESTPOOL1 + + log_must rm -f $CPATH $CPATHBKP $CPATHBKP2 $MD5FILE $MD5FILE2 + + log_must rm -rf $DEVICE_DIR/* + typeset i=0 + while (( i < $MAX_NUM )); do + log_must mkfile $FILE_SIZE ${DEVICE_DIR}/${DEVICE_FILE}$i + ((i += 1)) + done +} + +# +# Write a bit of data and sync several times. +# This function is intended to be used by zpool rewind tests. +# +function sync_some_data_a_few_times +{ + typeset pool=$1 + typeset -i a_few_times=${2:-10} + + typeset file="/$pool/tmpfile" + for i in {0..$a_few_times}; do + dd if=/dev/urandom of=${file}_$i bs=128k count=10 + sync + done + + return 0 +} + +# +# Just write a moderate amount of data to the pool. +# +function write_some_data +{ + typeset pool=$1 + typeset files10mb=${2:-10} + + typeset ds="$pool/fillerds" + zfs create $ds + [[ $? -ne 0 ]] && return 1 + + # Create 100 MB of data + typeset file="/$ds/fillerfile" + for i in {1..$files10mb}; do + dd if=/dev/urandom of=$file.$i bs=128k count=80 + [[ $? -ne 0 ]] && return 1 + done + + return 0 +} + +# +# Create/overwrite a few datasets with files. +# Apply md5sum on all the files and store checksums in a file. +# +# newdata: overwrite existing files if false. +# md5file: file where to store md5sums +# datasetname: base name for datasets +# +function _generate_data_common +{ + typeset pool=$1 + typeset newdata=$2 + typeset md5file=$3 + typeset datasetname=$4 + + typeset -i datasets=3 + typeset -i files=5 + typeset -i blocks=10 + + [[ -n $md5file ]] && rm -f $md5file + for i in {1..$datasets}; do + ( $newdata ) && log_must zfs create "$pool/$datasetname$i" + for j in {1..$files}; do + typeset file="/$pool/$datasetname$i/file$j" + dd if=/dev/urandom of=$file bs=128k count=$blocks > /dev/null + [[ -n $md5file ]] && md5sum $file >> $md5file + done + ( $newdata ) && sync + done + + return 0 +} + +function generate_data +{ + typeset pool=$1 + typeset md5file="$2" + typeset datasetname=${3:-ds} + + _generate_data_common $pool true "$md5file" $datasetname +} + +function overwrite_data +{ + typeset pool=$1 + typeset md5file="$2" + typeset datasetname=${3:-ds} + + _generate_data_common $1 false "$md5file" $datasetname +} + +# +# Verify md5sums of every file in md5sum file $1. +# +function verify_data_md5sums +{ + typeset md5file=$1 + + if [[ ! -f $md5file ]]; then + log_note "md5 sums file '$md5file' doesn't exist" + return 1 + fi + + md5sum -c --quiet $md5file + return $? +} + +# +# Set devices size in DEVICE_DIR to $1. +# +function increase_device_sizes +{ + typeset newfilesize=$1 + + typeset -i i=0 + while (( i < $MAX_NUM )); do + log_must mkfile $newfilesize ${DEVICE_DIR}/${DEVICE_FILE}$i + ((i += 1)) + done +} + +# +# Translate vdev names returned by zpool status into more generic names. +# +# eg: mirror-2 --> mirror +# +function _translate_vdev +{ + typeset vdev=$1 + + typeset keywords="mirror replacing raidz1 raidz2 raidz3 indirect" + for word in $keywords; do + echo $vdev | egrep "^${word}-[0-9]+\$" > /dev/null + if [[ $? -eq 0 ]]; then + vdev=$word + break + fi + done + + [[ $vdev == "logs" ]] && echo "log" && return 0 + [[ $vdev == "raidz1" ]] && echo "raidz" && return 0 + + echo $vdev + return 0 +} + +# +# Check that pool configuration returned by zpool status matches expected +# configuration. Format for the check string is same as the vdev arguments for +# creating a pool +# Add -q for quiet mode. +# +# eg: check_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0 log c1t1d0s0" +# +function check_pool_config +{ + typeset logfailure=true + if [[ $1 == '-q' ]]; then + logfailure=false + shift + fi + + typeset poolname=$1 + typeset expected=$2 + + typeset status + status=$(zpool status $poolname 2>&1) + if [[ $? -ne 0 ]]; then + if ( $logfailure ); then + log_note "zpool status $poolname failed: $status" + fi + return 1 + fi + + typeset actual="" + typeset began=false + printf "$status\n" | while read line; do + typeset vdev=$(echo "$line" | awk '{printf $1}') + if ( ! $began ) && [[ $vdev == NAME ]]; then + began=true + continue + fi + ( $began ) && [[ -z $vdev ]] && break; + + if ( $began ); then + [[ -z $actual ]] && actual="$vdev" && continue + vdev=$(_translate_vdev $vdev) + actual="$actual $vdev" + fi + done + + expected="$poolname $expected" + + if [[ "$actual" != "$expected" ]]; then + if ( $logfailure ); then + log_note "expected pool vdevs:" + log_note "> '$expected'" + log_note "actual pool vdevs:" + log_note "> '$actual'" + fi + return 1 + fi + + return 0 +} + +# +# Check that pool configuration returned by zpool status matches expected +# configuration within a given timeout in seconds. See check_pool_config(). +# +# eg: wait_for_pool_config pool1 "mirror c0t0d0s0 c0t1d0s0" 60 +# +function wait_for_pool_config +{ + typeset poolname=$1 + typeset expectedconfig="$2" + typeset -i timeout=${3:-60} + + timeout=$(( $timeout + $(date +%s) )) + + while (( $(date +%s) < $timeout )); do + check_pool_config -q $poolname "$expectedconfig" + [[ $? -eq 0 ]] && return 0 + sleep 3 + done + + check_pool_config $poolname "$expectedconfig" + return $? +} + +# +# Check that pool status is ONLINE +# +function check_pool_healthy +{ + typeset pool=$1 + + typeset status + status=$(zpool status $pool 2>&1) + if [[ $? -ne 0 ]]; then + log_note "zpool status $pool failed: $status" + return 1 + fi + + status=$(echo "$status" | grep "$pool" | grep -v "pool:" | \ + awk '{print $2}') + + if [[ $status != "ONLINE" ]]; then + log_note "Invalid zpool status for '$pool': '$status'" \ + "!= 'ONLINE'" + return 1 + fi + + return 0 +} + +# +# Return 0 if a device is currently being replaced in the pool. +# +function pool_is_replacing +{ + typeset pool=$1 + + zpool status $pool | grep "replacing" | grep "ONLINE" > /dev/null + + return $? +} + +function set_vdev_validate_skip +{ + mdb_set_uint32 "vdev_validate_skip" "$1" +} + +function get_zfs_txg_timeout +{ + echo $(mdb_get_uint32 "zfs_txg_timeout") +} + +function set_zfs_txg_timeout +{ + mdb_set_uint32 "zfs_txg_timeout" "$1" +} + +function set_spa_load_verify_metadata +{ + mdb_set_uint32 "spa_load_verify_metadata" "$1" +} + +function set_spa_load_verify_data +{ + mdb_set_uint32 "spa_load_verify_data" "$1" +} + +function set_zfs_max_missing_tvds +{ + mdb_set_uint32 "zfs_max_missing_tvds" "$1" +} + +# +# Use mdb to find the last txg that was synced in an active pool. +# +function get_last_txg_synced +{ + typeset pool=$1 + + typeset spas + spas=$(mdb -k -e "::spa") + [[ $? -ne 0 ]] && return 1 + + typeset spa="" + print "$spas\n" | while read line; do + typeset poolname=$(echo "$line" | awk '{print $3}') + typeset addr=$(echo "$line" | awk '{print $1}') + if [[ $poolname == $pool ]]; then + spa=$addr + break + fi + done + if [[ -z $spa ]]; then + log_fail "Couldn't find pool '$pool'" + return 1 + fi + typeset mdbcmd="$spa::print spa_t spa_ubsync.ub_txg | ::eval '.=E'" + typeset -i txg + txg=$(mdb -k -e "$mdbcmd") + [[ $? -ne 0 ]] && return 1 + + echo $txg + return 0 +} diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib b/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib index a82d3b3d59..8f1f30ed26 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib @@ -512,11 +512,13 @@ function test_fs_setup { typeset sendfs=$1 typeset recvfs=$2 + typeset streamfs=$3 typeset sendpool=${sendfs%%/*} typeset recvpool=${recvfs%%/*} datasetexists $sendfs && log_must zfs destroy -r $sendpool datasetexists $recvfs && log_must zfs destroy -r $recvpool + datasetexists $streamfs && log_must zfs destroy -r $streamfs if $(datasetexists $sendfs || zfs create -o compress=lz4 $sendfs); then mk_files 1000 256 0 $sendfs & @@ -545,10 +547,7 @@ function test_fs_setup ">/$sendpool/incremental.zsend" fi - if datasetexists $streamfs; then - log_must zfs destroy -r $streamfs - fi - log_must zfs create -o compress=lz4 $sendpool/stream + log_must zfs create -o compress=lz4 $streamfs } # @@ -661,9 +660,10 @@ function resume_cleanup { typeset sendfs=$1 typeset streamfs=$2 + typeset sendpool=${sendfs%%/*} datasetexists $sendfs && log_must zfs destroy -r $sendfs datasetexists $streamfs && log_must zfs destroy -r $streamfs cleanup_pool $POOL2 - rm -f /$POOL/initial.zsend /$POOL/incremental.zsend + rm -f /$sendpool/initial.zsend /$sendpool/incremental.zsend } diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh index 79c9bb6d9b..3cd1a8eece 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh @@ -43,8 +43,8 @@ sendfs=$POOL/sendfs recvfs=$POOL3/recvfs streamfs=$POOL2/stream -for sendfs in $POOL2/sendfs $POOL2; do - test_fs_setup $sendfs $recvfs +for sendfs in $POOL2/sendfs $POOL3; do + test_fs_setup $sendfs $recvfs $streamfs resume_test "zfs send -v $sendfs@a" $streamfs $recvfs resume_test "zfs send -v -i @a $sendfs@b" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh index 97c19f505a..958131e6d9 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh @@ -42,7 +42,7 @@ streamfs=$POOL/stream log_onexit resume_cleanup $sendfs $streamfs -test_fs_setup $sendfs $recvfs +test_fs_setup $sendfs $recvfs $streamfs resume_test "zfs send -D -v $sendfs@a" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh index 2d2a3304da..39121b12ec 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh @@ -44,7 +44,7 @@ streamfs=$POOL/stream log_onexit resume_cleanup $sendfs $streamfs -test_fs_setup $sendfs $recvfs +test_fs_setup $sendfs $recvfs $streamfs resume_test "zfs send -v -e $sendfs@a" $streamfs $recvfs resume_test "zfs send -v -e -i @a $sendfs@b" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh index 9592cb9a79..57eb594051 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh @@ -47,7 +47,7 @@ streamfs=$POOL/stream log_onexit resume_cleanup $sendfs $streamfs -test_fs_setup $sendfs $recvfs +test_fs_setup $sendfs $recvfs $streamfs log_must zfs bookmark $sendfs@a $sendfs#bm_a log_must zfs destroy $sendfs@a log_must zfs receive -v $recvfs </$POOL/initial.zsend diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh index d5d938e4b7..fc586cf8ee 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh @@ -44,7 +44,7 @@ streamfs=$POOL/stream log_onexit resume_cleanup $sendfs $streamfs -test_fs_setup $sendfs $recvfs +test_fs_setup $sendfs $recvfs $streamfs log_must zfs unmount $sendfs resume_test "zfs send $sendfs" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/send-c_resume.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/send-c_resume.ksh index 8b36177647..d5873788d9 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/send-c_resume.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/send-c_resume.ksh @@ -41,7 +41,7 @@ streamfs=$POOL/stream log_assert "Verify compressed send streams can be resumed if interrupted" log_onexit resume_cleanup $sendfs $streamfs -test_fs_setup $sendfs $recvfs +test_fs_setup $sendfs $recvfs $streamfs resume_test "zfs send -c -v $sendfs@a" $streamfs $recvfs resume_test "zfs send -c -v -i @a $sendfs@b" $streamfs $recvfs file_check $sendfs $recvfs |