summaryrefslogtreecommitdiff
path: root/usr/src/test/zfs-tests/tests/functional/refreserv/refreserv_multi_raidz.ksh
blob: ec5e0bfc276491ff80e16a6d8bb023827f71cdf5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright 2019 Joyent, Inc.
#

. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/refreserv/refreserv.cfg

#
# DESCRIPTION:
#	raidz refreservation=auto picks worst raidz vdev
#
# STRATEGY:
#	1. Create a pool with a single raidz vdev
#	2. For each block size [512b, 1k, 128k] or [4k, 8k, 128k]
#	    - create a volume
#	    - remember its refreservation
#	    - destroy the volume
#	3. Destroy the pool
#	4. Recreate the pool with one more disk in the vdev, then repeat steps
#	   2 and 3.
#
# NOTES:
#	1. This test will use up to 14 disks but can cover the key concepts with
#	   5 disks.
#	2. If the disks are a mixture of 4Kn and 512n/512e, failures are likely.
#

verify_runnable "global"

typeset -a alldisks=($DISKS)

# The larger the volsize, the better zvol_volsize_to_reservation() is at
# guessing the right number - though it is horrible with tiny blocks.  At 10M on
# ashift=12, the estimate may be over 26% too high.
volsize=100

function cleanup
{
	default_cleanup_noexit
	default_setup_noexit "${alldisks[0]}"
}

log_assert "raidz refreservation=auto picks worst raidz vdev"
log_onexit cleanup

poolexists "$TESTPOOL" && log_must zpool destroy "$TESTPOOL"

# Testing tiny block sizes on ashift=12 pools causes so much size inflation
# that small test disks may fill before creating small volumes.  However,
# testing 512b and 1K blocks on ashift=9 pools is an ok approximation for
# testing the problems that arise from 4K and 8K blocks on ashift=12 pools.
bps=$(prtvtoc /dev/rdsk/${alldisks[0]} |
    awk '$NF == "bytes/sector" { print $2; exit 0 }')
case "$bps" in
512)
	allshifts=(9 10 17)
	;;
4096)
	allshifts=(12 13 17)
	;;
*)
	log_fail "bytes/sector != (512|4096)"
	;;
esac
log_note "Testing in ashift=${allshifts[0]} mode"

typeset -A sizes=

#
# Determine the refreservation for a $volsize MiB volume on each raidz type at
# various block sizes.
#
for parity in 1 2 3; do
	raid=raidz$parity
	typeset -A sizes["$raid"]

	# Ensure we hit scenarios with and without skip blocks
	for ndisks in $((parity * 2)) $((parity * 2 + 1)); do
		typeset -a disks=(${alldisks[0..$((ndisks - 1))]})

		if (( ${#disks[@]} < ndisks )); then
			log_note "Too few disks to test $raid-$ndisks"
			continue
		fi

		typeset -A sizes["$raid"]["$ndisks"]

		log_must zpool create "$TESTPOOL" "$raid" "${disks[@]}"

		for bits in "${allshifts[@]}"; do
			vbs=$((1 << bits))
			log_note "Gathering refreservation for $raid-$ndisks" \
			    "volblocksize=$vbs"

			vol=$TESTPOOL/$TESTVOL
			log_must zfs create -V ${volsize}m \
			    -o volblocksize=$vbs "$vol"

			refres=$(zfs get -Hpo value refreservation "$vol")
			log_must test -n "$refres"
			sizes["$raid"]["$ndisks"]["$vbs"]=$refres

			log_must zfs destroy "$vol"
		done

		log_must zpool destroy "$TESTPOOL"
	done
done

# A little extra info is always helpful when diagnosing problems.  To
# pretty-print what you find in the log, do this in ksh:
#   typeset -A sizes=(...)
#   print -v sizes
log_note "sizes=$(print -C sizes)"

#
# Helper furnction for checking that refreservation is calculated properly in
# multi-vdev pools.  "Properly" is defined as assuming that all vdevs are as
# space inefficient as the worst one.
#
function check_vdevs {
	typeset raid=$1
	typeset nd1=$2
	typeset nd2=$3
	typeset -a disks1 disks2
	typeset vbs vol refres refres1 refres2 expect

	disks1=(${alldisks[0..$((nd1 - 1))]})
	disks2=(${alldisks[$nd1..$((nd1 + nd2 - 1))]})
	if (( ${#disks2[@]} < nd2 )); then
		log_note "Too few disks to test $raid-$nd1 + $raid=$nd2"
		return
	fi

	log_must zpool create -f "$TESTPOOL" \
	    "$raid" "${disks1[@]}" "$raid" "${disks2[@]}"

	for bits in "${allshifts[@]}"; do
		vbs=$((1 << bits))
		log_note "Verifying $raid-$nd1 $raid-$nd2 volblocksize=$vbs"

		vol=$TESTPOOL/$TESTVOL
		log_must zfs create -V ${volsize}m -o volblocksize=$vbs "$vol"
		refres=$(zfs get -Hpo value refreservation "$vol")
		log_must test -n "$refres"

		refres1=${sizes["$raid"]["$nd1"]["$vbs"]}
		refres2=${sizes["$raid"]["$nd2"]["$vbs"]}

		if (( refres1 > refres2 )); then
			log_note "Expecting refres ($refres) to match refres" \
			   "from $raid-$nd1 ($refres1)"
			log_must test "$refres" -eq "$refres1"
		else
			log_note "Expecting refres ($refres) to match refres" \
			   "from $raid-$nd1 ($refres2)"
			log_must test "$refres" -eq "$refres2"
		fi

		log_must zfs destroy "$vol"
	done

	log_must zpool destroy "$TESTPOOL"
}

#
# Verify that multi-vdev pools use the last optimistic size for all the
# permutations within a particular raidz variant.
#
for raid in "${!sizes[@]}"; do
	# ksh likes to create a [0] item for us.  Thanks, ksh!
	[[ $raid == "0" ]] && continue

	for nd1 in "${!sizes["$raid"][@]}"; do
		[[ $nd1 == "0" ]] && continue

		for nd2 in "${!sizes["$raid"][@]}"; do
			[[ $nd2 == "0" ]] && continue

			check_vdevs "$raid" "$nd1" "$nd2"
		done
	done
done

log_pass "raidz refreservation=auto picks worst raidz vdev"