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 egrep -v -e "records in" -e "records out" \ 119 -e "bytes.*copied" 120 ((filenum+=1)) 121 done 122 done 123 124 #################### 125 # Testing showed that on some devices, unless the pool is 126 # synchronized, that the block counts will be below the 127 # anticipated sizes since not all of the blocks will be flushed 128 # to the device. This 'sync' command prevents that from 129 # happening. 130 #################### 131 log_must zpool sync ${pool} 132} 133function histo_check_test_pool 134{ 135 if [ $# -ne 1 ]; then 136 log_note "histo_check_test_pool: insufficient parameters" 137 log_fail "hctp: 1 requested $# received" 138 fi 139 typeset pool=$1 140 141 set -A recordsizes 142 set -A recordcounts 143 typeset -i rb 144 typeset -i min_rsbits=9 #512 145 typeset -i max_rsbits=SPA_MAXBLOCKSHIFT+1 146 typeset -i this_rs 147 typeset -i this_ri 148 typeset -i sum_filesizes=0 149 typeset dumped 150 typeset stripped 151 152 let histo_check_pool_size=$(get_pool_prop size ${pool}) 153 if [[ ! ${histo_check_pool_size} =~ ${re_number} ]]; then 154 log_fail "histo_check_pool_size is not numeric ${histo_check_pool_size}" 155 fi 156 let max_pool_record_size=$(get_prop recordsize ${pool}) 157 if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then 158 log_fail "hctp: max_pool_record_size is not numeric ${max_pool_record_size}" 159 fi 160 161 dumped="${TEST_BASE_DIR}/${pool}_dump.txt" 162 stripped="${TEST_BASE_DIR}/${pool}_stripped.txt" 163 164 zdb -Pbbb ${pool} | \ 165 tee ${dumped} | \ 166 sed -e '1,/^block[ ][ ]*psize[ ][ ]*lsize.*$/d' \ 167 -e '/^size[ ]*Count/d' -e '/^$/,$d' \ 168 > ${stripped} 169 170 sum_filesizes=$(echo "2^21"|bc) 171 172 ################### 173 # generate 10% + 20% + 30% + 31% = 91% of the filespace 174 # attempting to use 100% will lead to no space left on device 175 # attempting to use 100% will lead to no space left on device 176 # Heuristic testing showed that 91% was the practical upper 177 # bound on the default 4G zpool (mirrored) that is used in 178 # testing. 179 # 180 # In order to expedite testing, we will only fill 2G (of 4G) 181 # of the test pool. You may want to modify this for 182 # standalone testing. 183 # 184 # In filling only 50% of the pool, we create one object on 185 # each "pass" below to achieve multiple objects per record 186 # size. Creating one file per object would lead to 187 # excessive file creation time. 188 ################### 189 # for pass in 10 20 30 31 # 91% 190 for pass in 20 20 10 # 50% 191 do 192 ((thiscount=(((histo_check_pool_size*pass)/100)/sum_filesizes))) 193 194 for rb in $(seq ${min_rsbits} ${max_rsbits}) 195 do 196 blksize=$(echo "2^$rb"|bc) 197 if [ $blksize -le $max_pool_record_size ]; then 198 ((recordcounts[$blksize]+=thiscount)) 199 fi 200 done 201 done 202 203 ################### 204 # compare the above computed counts for blocks against 205 # lsize count. Since some devices have a minimum hardware 206 # blocksize > 512, we cannot compare against the asize count. 207 # E.G., if the HWBlocksize = 4096, then the asize counts for 208 # 512, 1024 and 2048 will be zero and rolled up into the 209 # 4096 blocksize count for asize. For verification we stick 210 # to just lsize counts. 211 # 212 # The max_variance is hard-coded here at 10%. testing so far 213 # has shown this to be in the range of 2%-8% so we leave a 214 # generous allowance... This might need changes in the future 215 ################### 216 let max_variance=10 217 let fail_value=0 218 let error_count=0 219 log_note "Comparisons for ${pool}" 220 log_note "Bsize is the blocksize, Count is predicted value" 221 log_note "Bsize\tCount\tpsize\tlsize\tasize" 222 while read -r blksize pc pl pm lc ll lm ac al am 223 do 224 if [ $blksize -gt $max_pool_record_size ]; then 225 continue 226 fi 227 log_note \ 228 "$blksize\t${recordcounts[${blksize}]}\t$pc\t$lc\t$ac" 229 230 ################### 231 # get the computer record count and compute the 232 # difference percentage in integer arithmetic 233 ################### 234 rc=${recordcounts[${blksize}]} 235 ((rclc=(rc-lc)<0?lc-rc:rc-lc)) # absolute value 236 ((dp=(rclc*100)/rc)) 237 238 ################### 239 # Check against the allowed variance 240 ################### 241 if [ $dp -gt ${max_variance} ]; then 242 log_note \ 243 "Expected variance < ${max_variance}% observed ${dp}%" 244 if [ ${dp} -gt ${fail_value} ]; then 245 fail_value=${dp} 246 ((error_count++)) 247 fi 248 fi 249 done < ${stripped} 250 if [ ${fail_value} -gt 0 ]; then 251 if [ ${error_count} -eq 1 ]; then 252 log_note "hctp: There was ${error_count} error" 253 else 254 log_note "hctp:There were a total of ${error_count} errors" 255 fi 256 log_fail \ 257 "hctp: Max variance of ${max_variance}% exceeded, saw ${fail_value}%" 258 fi 259} 260 261log_assert "Verify zdb -Pbbb (block histogram) works as expected" 262log_onexit cleanup 263verify_runnable "global" 264verify_disk_count "$DISKS" 2 265 266default_mirror_setup_noexit $DISKS 267 268histo_populate_test_pool $TESTPOOL 269 270histo_check_test_pool $TESTPOOL 271 272log_pass "Histogram for zdb" 273