]>
Commit | Line | Data |
---|---|---|
a1d477c2 MA |
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 | # | |
d2734cce | 17 | # Copyright (c) 2014, 2017 by Delphix. All rights reserved. |
a1d477c2 MA |
18 | # |
19 | ||
20 | export REMOVEDISK=${DISKS%% *} | |
21 | export NOTREMOVEDISK=${DISKS##* } | |
22 | ||
23 | # | |
d2734cce | 24 | # Waits for the pool to finish a removal. |
a1d477c2 | 25 | # |
d2734cce | 26 | function wait_for_removal # pool |
a1d477c2 MA |
27 | { |
28 | typeset pool=$1 | |
29 | typeset callback=$2 | |
30 | ||
e60e158e | 31 | log_must zpool wait -t remove $pool |
a1d477c2 MA |
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 | |
38 | ||
39 | log_must is_pool_removed $pool | |
40 | return 0 | |
41 | } | |
42 | ||
d2734cce SD |
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 | # | |
56 | function attempt_during_removal # pool disk callback [args] | |
57 | { | |
58 | typeset pool=$1 | |
59 | typeset disk=$2 | |
60 | typeset callback=$3 | |
61 | ||
62 | shift 3 | |
cef48f14 | 63 | set_tunable32 zfs_removal_suspend_progress 1 |
d2734cce SD |
64 | |
65 | log_must zpool remove $pool $disk | |
66 | ||
67 | # | |
68 | # We want to make sure that the removal started | |
69 | # before issuing the callback. | |
70 | # | |
71 | sync | |
72 | log_must is_pool_removing $pool | |
73 | ||
74 | log_must $callback "$@" | |
75 | ||
76 | # | |
77 | # Ensure that we still haven't finished the removal | |
78 | # as expected. | |
79 | # | |
80 | log_must is_pool_removing $pool | |
81 | ||
cef48f14 | 82 | set_tunable32 zfs_removal_suspend_progress 0 |
d2734cce SD |
83 | |
84 | log_must wait_for_removal $pool | |
85 | log_mustnot vdevs_in_pool $pool $disk | |
86 | return 0 | |
87 | } | |
88 | ||
a1d477c2 MA |
89 | function indirect_vdev_mapping_size # pool |
90 | { | |
91 | typeset pool=$1 | |
92 | zdb -P $pool | grep 'indirect vdev' | \ | |
93 | sed -E 's/.*\(([0-9]+) in memory\).*/\1/g' | |
94 | } | |
95 | ||
96 | function random_write # file write_size | |
97 | { | |
98 | typeset file=$1 | |
99 | typeset block_size=$2 | |
7839c4b5 | 100 | typeset file_size=$(stat_size $file 2>/dev/null) |
a1d477c2 MA |
101 | typeset nblocks=$((file_size / block_size)) |
102 | ||
103 | [[ -w $file ]] || return 1 | |
104 | ||
105 | dd if=/dev/urandom of=$file conv=notrunc \ | |
106 | bs=$block_size count=1 seek=$((RANDOM % nblocks)) >/dev/null 2>&1 | |
107 | } | |
108 | ||
a1d477c2 MA |
109 | function start_random_writer # file |
110 | { | |
111 | typeset file=$1 | |
112 | ( | |
113 | log_note "Starting writer for $file" | |
114 | # This will fail when we destroy the pool. | |
115 | while random_write $file $((2**12)); do | |
116 | : | |
117 | done | |
118 | log_note "Stopping writer for $file" | |
119 | ) & | |
120 | } | |
121 | ||
d2734cce | 122 | function test_removal_with_operation # callback [args] |
a1d477c2 | 123 | { |
a1d477c2 MA |
124 | # |
125 | # To ensure that the removal takes a while, we fragment the pool | |
126 | # by writing random blocks and continue to do during the removal. | |
127 | # | |
128 | log_must mkfile 1g $TESTDIR/$TESTFILE0 | |
129 | for i in $(seq $((2**10))); do | |
130 | random_write $TESTDIR/$TESTFILE0 $((2**12)) || \ | |
131 | log_fail "Could not write to $TESTDIR/$TESTFILE0." | |
132 | done | |
133 | start_random_writer $TESTDIR/$TESTFILE0 1g | |
134 | killpid=$! | |
135 | ||
d2734cce | 136 | log_must attempt_during_removal $TESTPOOL $REMOVEDISK "$@" |
a1d477c2 MA |
137 | log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK |
138 | log_must zdb -cd $TESTPOOL | |
139 | ||
140 | kill $killpid | |
141 | wait | |
7c9a4292 BB |
142 | |
143 | verify_pool $TESTPOOL | |
a1d477c2 MA |
144 | } |
145 | ||
146 | # | |
147 | # Kill the background job use by the test_removal_with_operation function. | |
148 | # | |
149 | function test_removal_with_operation_kill | |
150 | { | |
151 | kill $killpid | |
152 | wait $killpid | |
153 | return 0 | |
154 | } |