xref: /illumos-gate/usr/src/test/zfs-tests/tests/functional/fault/auto_spare_sorted_001_pos.ksh (revision d5b563f27eb78296f57dddced6755afe7445c4b9)
1#!/bin/ksh
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright 2024 OmniOS Community Edition (OmniOSce) Association.
15#
16
17. $STF_SUITE/include/libtest.shlib
18
19#
20# DESCRIPTION:
21#	Automated auto-spare selects lowest capacity suitable device
22#
23# STRATEGY:
24#	1. Create a redundant pool with two spare devices of different sizes,
25#	   one that matches the size of the other devices in the pool, and one
26#	   twice as large.
27#	2. Manually fault a device, wait for the hot-spare and verify that
28#	   the smallest device is selected.
29#	3. Repeat with the devices added to the pool in the opposite order.
30#	4. Repeat with the faulted vdev being the same size as the larger
31#	   spare and verify that the larger spare is selected.
32#
33
34verify_runnable "global"
35
36function cleanup {
37	log_must zinject -c all
38	poolexists $TESTPOOL && destroy_pool $TESTPOOL
39	log_must rm -f ${DATA_DEVS[*]} ${SPARE_DEVS[*]}
40}
41
42log_assert "Automated auto-spare selects lowest capacity suitable device"
43log_onexit cleanup
44
45typeset -a DATA_DEVS SPARE_DEVS
46typeset DEV
47TMPDIR='/var/tmp'
48for d in {1..4}; do
49	DEV="$TMPDIR/data-dev$d"
50	typeset -r "DATA_DEV$d"="$DEV"
51	DATA_DEVS+=($DEV)
52done
53for d in {1..2}; do
54	DEV="$TMPDIR/data-dev$d"
55	typeset -r "SPARE_DEV$d"="$TMPDIR/spare-dev$d"
56	SPARE_DEVS+=($DEV)
57done
58
59function run {
60	typeset type="$1"; shift
61	typeset ddevsize="$1"; shift	# Data dev size
62	typeset spare1="$1"; shift	# First spare to add
63	typeset spare2="$1"; shift	# Second spare to add
64	typeset spare="$1"; shift	# Expected spare that gets picked
65
66	truncate -s $ddevsize ${DATA_DEVS[*]}
67	truncate -s $SPA_MINDEVSIZE $SPARE_DEV1
68	truncate -s $((SPA_MINDEVSIZE * 2)) $SPARE_DEV2
69
70	log_must zpool create $TESTPOOL $type ${DATA_DEVS[*]}
71	log_must zpool add $TESTPOOL spare "$spare1"
72	log_must zpool add $TESTPOOL spare "$spare2"
73
74	# Fault a device, verify the right spare is kicked in
75	log_must zinject -d $DATA_DEV1 -e nxio -T all -f 100 $TESTPOOL
76	log_must zpool scrub $TESTPOOL
77	log_must wait_vdev_state $TESTPOOL $DATA_DEV1 "UNAVAIL" 60
78	log_must wait_vdev_state $TESTPOOL $spare "ONLINE" 60
79	log_must wait_hotspare_state $TESTPOOL $spare "INUSE"
80	log_must check_state $TESTPOOL "$type-0" "DEGRADED"
81	cleanup
82}
83
84for type in mirror raidz1 raidz2 raidz3; do
85	# All vdevs and spare1 are the same size, spare2 is double the size.
86	# Regardless of whether spare1 or spare2 is added to the pool first, we
87	# expect spare1 to be used for the replacement.
88	run $type $SPA_MINDEVSIZE $SPARE_DEV1 $SPARE_DEV2 $SPARE_DEV1
89	run $type $SPA_MINDEVSIZE $SPARE_DEV2 $SPARE_DEV1 $SPARE_DEV1
90
91	# All vdevs and spare2 are the same size, spare1 is half the size.
92	# Regardless of whether spare1 or spare2 is added to the pool first, we
93	# expect spare2 to be used for the replacement. spare1 is too small.
94	run $type $((SPA_MINDEVSIZE * 2)) $SPARE_DEV1 $SPARE_DEV2 $SPARE_DEV2
95	run $type $((SPA_MINDEVSIZE * 2)) $SPARE_DEV2 $SPARE_DEV1 $SPARE_DEV2
96done
97
98log_pass "Automated auto-spare selects lowest capacity suitable device"
99