1# 2# CDDL HEADER START 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# CDDL HEADER END 14# 15 16# 17# Copyright (c) 2014, 2017 by Delphix. All rights reserved. 18# 19 20export REMOVEDISK=${DISKS%% *} 21export NOTREMOVEDISK=${DISKS##* } 22 23# 24# Waits for the pool to finish a removal. 25# 26function wait_for_removal # pool 27{ 28 typeset pool=$1 29 typeset callback=$2 30 31 log_must zpool wait -t remove $pool 32 33 # 34 # The pool state changes before the TXG finishes syncing; wait for 35 # the removal to be completed on disk. 36 # 37 sync_pool $pool 38 39 log_must is_pool_removed $pool 40 return 0 41} 42 43# 44# Removes the specified disk from its respective pool and 45# runs the callback while the removal is in progress. 46# 47# This function is mainly used to test how other operations 48# interact with device removal. After the callback is done, 49# the removal is unpaused and we wait for it to finish. 50# 51# Example usage: 52# 53# attempt_during_removal $TESTPOOL $DISK dd if=/dev/urandom \ 54# of=/$TESTPOOL/file count=1 55# 56function attempt_during_removal # pool disk callback [args] 57{ 58 typeset pool=$1 59 typeset disk=$2 60 typeset callback=$3 61 62 shift 3 63 log_onexit_push set_tunable32 REMOVAL_SUSPEND_PROGRESS 0 64 set_tunable32 REMOVAL_SUSPEND_PROGRESS 1 65 66 log_must zpool remove $pool $disk 67 68 # 69 # We want to make sure that the removal started 70 # before issuing the callback. 71 # 72 sync_pool $pool 73 log_must is_pool_removing $pool 74 75 log_must $callback "$@" 76 77 # 78 # Ensure that we still haven't finished the removal 79 # as expected. 80 # 81 log_must is_pool_removing $pool 82 83 set_tunable32 REMOVAL_SUSPEND_PROGRESS 0 84 log_onexit_pop 85 86 log_must wait_for_removal $pool 87 log_mustnot vdevs_in_pool $pool $disk 88 return 0 89} 90 91function random_write # file write_size 92{ 93 typeset file=$1 94 typeset block_size=$2 95 typeset file_size=$(stat_size $file 2>/dev/null) 96 typeset nblocks=$((file_size / block_size)) 97 98 [[ -w $file ]] || return 1 99 100 dd if=/dev/urandom of=$file conv=notrunc \ 101 bs=$block_size count=1 seek=$((RANDOM % nblocks)) >/dev/null 2>&1 102} 103 104function start_random_writer # file 105{ 106 typeset file=$1 107 ( 108 log_note "Starting writer for $file" 109 # This will fail when we destroy the pool. 110 while random_write $file $((2**12)); do 111 : 112 done 113 log_note "Stopping writer for $file" 114 ) & 115} 116 117function test_removal_with_operation # callback [args] 118{ 119 # 120 # To ensure that the removal takes a while, we fragment the pool 121 # by writing random blocks and continue to do during the removal. 122 # 123 log_must mkfile 1g $TESTDIR/$TESTFILE0 124 for i in $(seq $((2**10))); do 125 random_write $TESTDIR/$TESTFILE0 $((2**12)) || \ 126 log_fail "Could not write to $TESTDIR/$TESTFILE0." 127 done 128 start_random_writer $TESTDIR/$TESTFILE0 1g 129 killpid=$! 130 131 log_must attempt_during_removal $TESTPOOL $REMOVEDISK "$@" 132 log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK 133 log_must zdb -cd $TESTPOOL 134 135 kill $killpid 136 wait 137 138 verify_pool $TESTPOOL 139} 140 141# 142# Kill the background job use by the test_removal_with_operation function. 143# 144function test_removal_with_operation_kill 145{ 146 kill $killpid 147 wait $killpid 148 return 0 149} 150