]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/zfs-tests/tests/functional/refreserv/refreserv_multi_raidz.ksh
Vendor import of openzfs master @ 184df27eef0abdc7ab2105b21257f753834b936b
[FreeBSD/FreeBSD.git] / tests / zfs-tests / tests / functional / refreserv / refreserv_multi_raidz.ksh
1 #!/bin/ksh -p
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 2019 Joyent, Inc.
15 #
16
17 . $STF_SUITE/include/libtest.shlib
18 . $STF_SUITE/tests/functional/refreserv/refreserv.cfg
19
20 #
21 # DESCRIPTION:
22 #       raidz refreservation=auto picks worst raidz vdev
23 #
24 # STRATEGY:
25 #       1. Create a pool with a single raidz vdev
26 #       2. For each block size [512b, 1k, 128k] or [4k, 8k, 128k]
27 #           - create a volume
28 #           - remember its refreservation
29 #           - destroy the volume
30 #       3. Destroy the pool
31 #       4. Recreate the pool with one more disk in the vdev, then repeat steps
32 #          2 and 3.
33 #
34 # NOTES:
35 #       1. This test will use up to 14 disks but can cover the key concepts with
36 #          5 disks.
37 #       2. If the disks are a mixture of 4Kn and 512n/512e, failures are likely.
38 #
39
40 verify_runnable "global"
41
42 typeset -a alldisks=($DISKS)
43
44 # The larger the volsize, the better zvol_volsize_to_reservation() is at
45 # guessing the right number - though it is horrible with tiny blocks.  At 10M on
46 # ashift=12, the estimate may be over 26% too high.
47 volsize=100
48
49 function cleanup
50 {
51         default_cleanup_noexit
52         default_setup_noexit "${alldisks[0]}"
53 }
54
55 log_assert "raidz refreservation=auto picks worst raidz vdev"
56 log_onexit cleanup
57
58 poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
59
60 # Testing tiny block sizes on ashift=12 pools causes so much size inflation
61 # that small test disks may fill before creating small volumes.  However,
62 # testing 512b and 1K blocks on ashift=9 pools is an ok approximation for
63 # testing the problems that arise from 4K and 8K blocks on ashift=12 pools.
64 if is_freebsd; then
65         bps=$(diskinfo -v ${alldisks[0]} | awk '/sectorsize/ { print $1 }')
66 elif is_linux; then
67         bps=$(lsblk -nrdo min-io /dev/${alldisks[0]})
68 fi
69 case "$bps" in
70 512)
71         allshifts=(9 10 17)
72         ;;
73 4096)
74         allshifts=(12 13 17)
75         ;;
76 *)
77         log_fail "bytes/sector: $bps != (512|4096)"
78         ;;
79 esac
80 log_note "Testing in ashift=${allshifts[0]} mode"
81
82 typeset -A sizes=
83
84 #
85 # Determine the refreservation for a $volsize MiB volume on each raidz type at
86 # various block sizes.
87 #
88 for parity in 1 2 3; do
89         raid=raidz$parity
90         typeset -A sizes["$raid"]
91
92         # Ensure we hit scenarios with and without skip blocks
93         for ndisks in $((parity * 2)) $((parity * 2 + 1)); do
94                 typeset -a disks=(${alldisks[0..$((ndisks - 1))]})
95
96                 if (( ${#disks[@]} < ndisks )); then
97                         log_note "Too few disks to test $raid-$ndisks"
98                         continue
99                 fi
100
101                 typeset -A sizes["$raid"]["$ndisks"]
102
103                 log_must zpool create "$TESTPOOL" "$raid" "${disks[@]}"
104
105                 for bits in "${allshifts[@]}"; do
106                         vbs=$((1 << bits))
107                         log_note "Gathering refreservation for $raid-$ndisks" \
108                             "volblocksize=$vbs"
109
110                         vol=$TESTPOOL/$TESTVOL
111                         log_must zfs create -V ${volsize}m \
112                             -o volblocksize=$vbs "$vol"
113
114                         refres=$(zfs get -Hpo value refreservation "$vol")
115                         log_must test -n "$refres"
116                         sizes["$raid"]["$ndisks"]["$vbs"]=$refres
117
118                         log_must_busy zfs destroy "$vol"
119                 done
120
121                 log_must_busy zpool destroy "$TESTPOOL"
122         done
123 done
124
125 # A little extra info is always helpful when diagnosing problems.  To
126 # pretty-print what you find in the log, do this in ksh:
127 #   typeset -A sizes=(...)
128 #   print -v sizes
129 log_note "sizes=$(print -C sizes)"
130
131 #
132 # Helper function for checking that refreservation is calculated properly in
133 # multi-vdev pools.  "Properly" is defined as assuming that all vdevs are as
134 # space inefficient as the worst one.
135 #
136 function check_vdevs {
137         typeset raid=$1
138         typeset nd1=$2
139         typeset nd2=$3
140         typeset -a disks1 disks2
141         typeset vbs vol refres refres1 refres2 expect
142
143         disks1=(${alldisks[0..$((nd1 - 1))]})
144         disks2=(${alldisks[$nd1..$((nd1 + nd2 - 1))]})
145         if (( ${#disks2[@]} < nd2 )); then
146                 log_note "Too few disks to test $raid-$nd1 + $raid=$nd2"
147                 return
148         fi
149
150         log_must zpool create -f "$TESTPOOL" \
151             "$raid" "${disks1[@]}" "$raid" "${disks2[@]}"
152
153         for bits in "${allshifts[@]}"; do
154                 vbs=$((1 << bits))
155                 log_note "Verifying $raid-$nd1 $raid-$nd2 volblocksize=$vbs"
156
157                 vol=$TESTPOOL/$TESTVOL
158                 log_must zfs create -V ${volsize}m -o volblocksize=$vbs "$vol"
159                 refres=$(zfs get -Hpo value refreservation "$vol")
160                 log_must test -n "$refres"
161
162                 refres1=${sizes["$raid"]["$nd1"]["$vbs"]}
163                 refres2=${sizes["$raid"]["$nd2"]["$vbs"]}
164
165                 if (( refres1 > refres2 )); then
166                         log_note "Expecting refres ($refres) to match refres" \
167                            "from $raid-$nd1 ($refres1)"
168                         log_must test "$refres" -eq "$refres1"
169                 else
170                         log_note "Expecting refres ($refres) to match refres" \
171                            "from $raid-$nd1 ($refres2)"
172                         log_must test "$refres" -eq "$refres2"
173                 fi
174
175                 log_must zfs destroy "$vol"
176         done
177
178         log_must zpool destroy "$TESTPOOL"
179 }
180
181 #
182 # Verify that multi-vdev pools use the last optimistic size for all the
183 # permutations within a particular raidz variant.
184 #
185 for raid in "${!sizes[@]}"; do
186         # ksh likes to create a [0] item for us.  Thanks, ksh!
187         [[ $raid == "0" ]] && continue
188
189         for nd1 in "${!sizes["$raid"][@]}"; do
190                 # And with an empty array we get one key, ''.  Thanks, ksh!
191                 [[ $nd1 == "0" || -z "$nd1" ]] && continue
192
193                 for nd2 in "${!sizes["$raid"][@]}"; do
194                         [[ $nd2 == "0" || -z "$nd2" ]] && continue
195
196                         check_vdevs "$raid" "$nd1" "$nd2"
197                 done
198         done
199 done
200
201 log_pass "raidz refreservation=auto picks worst raidz vdev"