1#! /bin/ksh -p
2#
3# CDDL HEADER START
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# CDDL HEADER END
15#
16
17#
18# Copyright (c) 2017 by Delphix. All rights reserved.
19#
20
21. $STF_SUITE/include/libtest.shlib
22. $STF_SUITE/tests/functional/removal/removal.kshlib
23
24#
25# DESCRIPTION:
26#
27# When a pool has an ongoing removal and it is exported ZFS
28# suspends the removal thread beforehand. This test ensures
29# that ZFS restarts the removal thread if the export fails
30# for some reason.
31#
32# STRATEGY:
33#
34# 1. Create a pool with one vdev and do some writes on it.
35# 2. Add a new vdev to the pool and start the removal of
36#    the first vdev.
37# 3. Inject a fault in the pool and attempt to export (it
38#    should fail).
39# 4. After the export fails ensure that the removal thread
40#    was restarted (i.e. the svr_thread field in the spa
41#    should be non-zero).
42#
43
44
45function cleanup
46{
47	log_must zinject -c all
48	default_cleanup_noexit
49}
50
51function ensure_thread_running # spa_address
52{
53	#
54	# Try to get the address of the removal thread.
55	#
56	typeset THREAD_ADDR=$(mdb -ke "$1::print \
57	    spa_t spa_vdev_removal->svr_thread" | awk "{print \$3}")
58
59	#
60	# if address is NULL it means that the thread is
61	# not running.
62	#
63        [[ "$THREAD_ADDR" = 0 ]] && \
64            log_fail "removal thread is not running"
65
66	return 0
67}
68
69log_onexit cleanup
70
71#
72# Create pool with one disk.
73#
74log_must default_setup_noexit "$REMOVEDISK"
75
76#
77# Save address of SPA in memory so you can check with mdb
78# if the removal thread is running.
79#
80typeset SPA_ADDR=$(mdb -ke "::spa" | awk "/$TESTPOOL/ {print \$1}")
81
82#
83# Turn off compression to raise capacity as much as possible
84# for the little time that this test runs.
85#
86log_must zfs set compression=off $TESTPOOL/$TESTFS
87
88#
89# Write some data that will be evacuated from the device when
90# we start the removal.
91#
92log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=64M count=5
93
94#
95# Add second device where all the data will be evacuated.
96#
97log_must zpool add -f $TESTPOOL $NOTREMOVEDISK
98
99#
100# Start removal.
101#
102log_must zpool remove $TESTPOOL $REMOVEDISK
103
104#
105# Inject an error so export fails after having just suspended
106# the removal thread. [spa_inject_ref gets incremented]
107#
108log_must zinject -d $REMOVEDISK -D 10:1 $TESTPOOL
109
110log_must ensure_thread_running $SPA_ADDR
111
112#
113# Because of the above error export should fail.
114#
115log_mustnot zpool export $TESTPOOL
116
117log_must ensure_thread_running $SPA_ADDR
118
119wait_for_removal $TESTPOOL
120
121log_pass "Device removal thread resumes after failed export"
122