1#!/bin/ksh -p 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) 2017 by Delphix. All rights reserved. 16# Copyright (c) 2020 by Lawrence Livermore National Security LLC. 17 18. $STF_SUITE/include/libtest.shlib 19 20 21# 22# DESCRIPTION: 23# Create a pool and populate it with files of various 24# recordsizes 25# 26# STRATEGY: 27# 1. Create pool 28# 2. Populate it 29# 3. Run zdb -Pbbb on pool 30# 4. Verify variance on blocksizes 31# 32function cleanup 33{ 34 datasetexists $TESTPOOL && destroy_pool $TESTPOOL 35} 36 37SPA_MAXBLOCKSHIFT=24 38 39function histo_populate_test_pool 40{ 41 if [ $# -ne 1 ]; then 42 log_note "histo_populate_test_pool: insufficient parameters" 43 log_fail "hptp: 1 requested $# received" 44 fi 45 typeset pool=$1 46 47 set -A recordsizes 48 typeset -i min_rsbits=9 #512 49 typeset -i max_rsbits=SPA_MAXBLOCKSHIFT #16 MiB 50 typeset -i sum_filesizes=0 51 re_number='^[0-9]+$' 52 53 let histo_pool_size=$(get_pool_prop size ${pool}) 54 if [[ ! ${histo_pool_size} =~ ${re_number} ]]; then 55 log_fail "histo_pool_size is not numeric ${pool_size}" 56 fi 57 let max_pool_record_size=$(get_prop recordsize ${pool}) 58 if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then 59 log_fail "hptp: max_pool_record_size is not numeric ${max_pool_record_size}" 60 fi 61 62 sum_filesizes=$(echo "2^21"|bc) 63 ((min_pool_size=12*sum_filesizes)) 64 if [ ${histo_pool_size} -lt ${min_pool_size} ]; then 65 log_note "hptp: Your pool size ${histo_pool_size}" 66 log_fail "hptp: is less than minimum ${min_pool_size}" 67 fi 68 this_ri=min_rsbits 69 file_num=0 70 total_count=0 71 ################### 72 # generate 10% + 20% + 30% + 31% = 91% of the filespace 73 # attempting to use 100% will lead to no space left on device 74 # Heuristic testing showed that 91% was the practical upper 75 # bound on the default 4G zpool (mirrored) that is used in 76 # testing. 77 # 78 # In order to expedite testing, we will only fill 2G (of 4G) 79 # of the test pool. You may want to modify this for 80 # standalone testing. 81 # 82 # In filling only 50% of the pool, we create one object on 83 # each "pass" below to achieve multiple objects per record 84 # size. Creating one file per object would lead to 85 # excessive file creation time. 86 ################### 87 # for pass in 10 20 30 31 # 91% 88 for pass in 20 20 10 # 50% 89 do 90 ((thiscount=(((histo_pool_size*pass)/100)/sum_filesizes))) 91 92 ((total_count+=thiscount)) 93 for rb in $(seq ${min_rsbits} ${max_rsbits}) 94 do 95 this_rs=$(echo "2^${rb}" | bc) 96 if [ ${this_rs} -gt ${max_pool_record_size} ]; then 97 continue 98 fi 99 100 if [ ! -d /${pool}/B_${this_rs} ]; then 101 zfs create ${pool}/B_${this_rs} 102 zfs set recordsize=${this_rs} \ 103 ${pool}/B_${this_rs} 104 fi 105 #################### 106 # Create the files in the devices and datasets 107 # of the right size. The files are filled 108 # with random data to defeat the compression 109 # 110 # Note that the dd output is suppressed unless 111 # there are errors 112 #################### 113 114 dd if=/dev/urandom \ 115 of=/${pool}/B_${this_rs}/file_${filenum} \ 116 bs=${this_rs} count=${thiscount} \ 117 iflag=fullblock 2>&1 | \ 118 grep -ve "records in" -e "records out" -e "bytes.*copied" 119 ((filenum+=1)) 120 done 121 done 122 123 #################### 124 # Testing showed that on some devices, unless the pool is 125 # synchronized, that the block counts will be below the 126 # anticipated sizes since not all of the blocks will be flushed 127 # to the device. This 'sync' command prevents that from 128 # happening. 129 #################### 130 sync_pool ${pool} 131} 132function histo_check_test_pool 133{ 134 if [ $# -ne 1 ]; then 135 log_note "histo_check_test_pool: insufficient parameters" 136 log_fail "hctp: 1 requested $# received" 137 fi 138 typeset pool=$1 139 140 set -A recordsizes 141 set -A recordcounts 142 typeset -i rb 143 typeset -i min_rsbits=9 #512 144 typeset -i max_rsbits=SPA_MAXBLOCKSHIFT+1 145 typeset -i this_rs 146 typeset -i this_ri 147 typeset -i sum_filesizes=0 148 149 let histo_check_pool_size=$(get_pool_prop size ${pool}) 150 if [[ ! ${histo_check_pool_size} =~ ${re_number} ]]; then 151 log_fail "histo_check_pool_size is not numeric ${histo_check_pool_size}" 152 fi 153 let max_pool_record_size=$(get_prop recordsize ${pool}) 154 if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then 155 log_fail "hctp: max_pool_record_size is not numeric ${max_pool_record_size}" 156 fi 157 158 stripped="${TEST_BASE_DIR}/${pool}_stripped.txt" 159 160 zdb -Pbbb ${pool} | \ 161 sed -e '1,/^block[ ][ ]*psize[ ][ ]*lsize.*$/d' \ 162 -e '/^size[ ]*Count/d' -e '/^$/,$d' \ 163 > ${stripped} 164 165 sum_filesizes=$(echo "2^21"|bc) 166 167 ################### 168 # generate 10% + 20% + 30% + 31% = 91% of the filespace 169 # attempting to use 100% will lead to no space left on device 170 # attempting to use 100% will lead to no space left on device 171 # Heuristic testing showed that 91% was the practical upper 172 # bound on the default 4G zpool (mirrored) that is used in 173 # testing. 174 # 175 # In order to expedite testing, we will only fill 2G (of 4G) 176 # of the test pool. You may want to modify this for 177 # standalone testing. 178 # 179 # In filling only 50% of the pool, we create one object on 180 # each "pass" below to achieve multiple objects per record 181 # size. Creating one file per object would lead to 182 # excessive file creation time. 183 ################### 184 # for pass in 10 20 30 31 # 91% 185 for pass in 20 20 10 # 50% 186 do 187 ((thiscount=(((histo_check_pool_size*pass)/100)/sum_filesizes))) 188 189 for rb in $(seq ${min_rsbits} ${max_rsbits}) 190 do 191 blksize=$(echo "2^$rb"|bc) 192 if [ $blksize -le $max_pool_record_size ]; then 193 ((recordcounts[$blksize]+=thiscount)) 194 fi 195 done 196 done 197 198 ################### 199 # compare the above computed counts for blocks against 200 # lsize count. Since some devices have a minimum hardware 201 # blocksize > 512, we cannot compare against the asize count. 202 # E.G., if the HWBlocksize = 4096, then the asize counts for 203 # 512, 1024 and 2048 will be zero and rolled up into the 204 # 4096 blocksize count for asize. For verification we stick 205 # to just lsize counts. 206 # 207 # The max_variance is hard-coded here at 12% to leave us some 208 # margin. Testing has shown this normally to be in the range 209 # of 2%-8%, but it may be as large as 11%. 210 ################### 211 let max_variance=12 212 let fail_value=0 213 let error_count=0 214 log_note "Comparisons for ${pool}" 215 log_note "Bsize is the blocksize, Count is predicted value" 216 log_note "Bsize\tCount\tpsize\tlsize\tasize" 217 while read -r blksize pc pl pm lc ll lm ac al am 218 do 219 if [ $blksize -gt $max_pool_record_size ]; then 220 continue 221 fi 222 log_note \ 223 "$blksize\t${recordcounts[${blksize}]}\t$pc\t$lc\t$ac" 224 225 ################### 226 # get the computer record count and compute the 227 # difference percentage in integer arithmetic 228 ################### 229 rc=${recordcounts[${blksize}]} 230 ((rclc=(rc-lc)<0?lc-rc:rc-lc)) # absolute value 231 ((dp=(rclc*100)/rc)) 232 233 ################### 234 # Check against the allowed variance 235 ################### 236 if [ $dp -gt ${max_variance} ]; then 237 log_note \ 238 "Expected variance < ${max_variance}% observed ${dp}%" 239 if [ ${dp} -gt ${fail_value} ]; then 240 fail_value=${dp} 241 ((error_count++)) 242 fi 243 fi 244 done < ${stripped} 245 rm "${stripped}" 246 247 if [ ${fail_value} -gt 0 ]; then 248 if [ ${error_count} -eq 1 ]; then 249 log_note "hctp: There was ${error_count} error" 250 else 251 log_note "hctp:There were a total of ${error_count} errors" 252 fi 253 log_fail \ 254 "hctp: Max variance of ${max_variance}% exceeded, saw ${fail_value}%" 255 fi 256} 257 258log_assert "Verify zdb -Pbbb (block histogram) works as expected" 259log_onexit cleanup 260verify_runnable "global" 261verify_disk_count "$DISKS" 2 262 263default_mirror_setup_noexit $DISKS 264 265histo_populate_test_pool $TESTPOOL 266 267histo_check_test_pool $TESTPOOL 268 269log_pass "Histogram for zdb" 270