1#!/bin/ksh
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) 2019, Datto Inc. All rights reserved.
16# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
17#
18
19. $STF_SUITE/include/libtest.shlib
20. $STF_SUITE/tests/functional/replacement/replacement.cfg
21
22#
23# Description:
24# Verify that attach/detach work while resilvering and attaching
25# multiple vdevs.
26#
27# Strategy:
28# 1. Create a single vdev pool
29# 2. While healing or sequential resilvering:
30#    a. Attach a vdev to convert the pool to a mirror.
31#    b. Attach a vdev to convert the pool to a 3-way mirror.
32#    c. Verify the original vdev cannot be removed (no redundant copies)
33#    d. Detach a vdev.  Healing and sequential resilver remain running.
34#    e. Detach a vdev.  Healing resilver remains running, sequential
35#       resilver is canceled.
36#    f. Wait for resilver to complete.
37#
38
39function cleanup
40{
41	log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
42	    $ORIG_SCAN_SUSPEND_PROGRESS
43	destroy_pool $TESTPOOL1
44	rm -f ${VDEV_FILES[@]}
45}
46
47log_assert "Verify attach/detach with multiple vdevs"
48
49ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
50
51log_onexit cleanup
52
53log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]}
54
55# Verify resilver resumes on import.
56log_must zpool create -f $TESTPOOL1 ${VDEV_FILES[0]}
57
58for replace_mode in "healing" "sequential"; do
59        #
60        # Resilvers abort the dsl_scan and reconfigure it for resilvering.
61        # Rebuilds cancel the dsl_scan and start the vdev_rebuild thread.
62        #
63        if [[ "$replace_mode" = "healing" ]]; then
64                flags=""
65        else
66                flags="-s"
67        fi
68
69	log_mustnot is_pool_resilvering $TESTPOOL1
70	log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
71
72	# Attach first vdev (stripe -> mirror)
73	log_must zpool attach $flags $TESTPOOL1 \
74	    ${VDEV_FILES[0]} ${VDEV_FILES[1]}
75	log_must is_pool_resilvering $TESTPOOL1
76
77	# Attach second vdev (2-way -> 3-way mirror)
78	log_must zpool attach $flags $TESTPOOL1 \
79	    ${VDEV_FILES[1]} ${VDEV_FILES[2]}
80	log_must is_pool_resilvering $TESTPOOL1
81
82	# Original vdev cannot be detached until there is sufficient redundancy.
83	log_mustnot zpool detach $TESTPOOL1 ${VDEV_FILES[0]}
84
85	# Detach first vdev (resilver keeps running)
86	log_must zpool detach $TESTPOOL1 ${VDEV_FILES[1]}
87	log_must is_pool_resilvering $TESTPOOL1
88
89	#
90	# Detach second vdev.  There's a difference in behavior between
91	# healing and sequential resilvers.  A healing resilver will not be
92	# cancelled even though there's nothing on the original vdev which
93	# needs to be rebuilt.  A sequential resilver on the otherhand is
94	# canceled when returning to a non-redundant striped layout.  At
95	# some point the healing resilver behavior should be updated to match
96	# the sequential resilver behavior.
97	#
98	log_must zpool detach $TESTPOOL1 ${VDEV_FILES[2]}
99
100        if [[ "$replace_mode" = "healing" ]]; then
101		log_must is_pool_resilvering $TESTPOOL1
102        else
103		log_mustnot is_pool_resilvering $TESTPOOL1
104        fi
105
106	log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
107	    $ORIG_SCAN_SUSPEND_PROGRESS
108	log_must zpool wait $TESTPOOL1
109done
110
111log_pass "Verify attach/detach with multiple vdevs"
112