diff --git a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh index 0a4d24fa695a..cfa26f54b11f 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh @@ -1,269 +1,269 @@ #!/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 (c) 2017 by Delphix. All rights reserved. # Copyright (c) 2020 by Lawrence Livermore National Security LLC. . $STF_SUITE/include/libtest.shlib # # DESCRIPTION: # Create a pool and populate it with files of various # recordsizes # # STRATEGY: # 1. Create pool # 2. Populate it # 3. Run zdb -Pbbb on pool # 4. Verify variance on blocksizes # function cleanup { datasetexists $TESTPOOL && destroy_pool $TESTPOOL } SPA_MAXBLOCKSHIFT=24 function histo_populate_test_pool { if [ $# -ne 1 ]; then log_note "histo_populate_test_pool: insufficient parameters" log_fail "hptp: 1 requested $# received" fi typeset pool=$1 set -A recordsizes typeset -i min_rsbits=9 #512 typeset -i max_rsbits=SPA_MAXBLOCKSHIFT #16 MiB typeset -i sum_filesizes=0 re_number='^[0-9]+$' let histo_pool_size=$(get_pool_prop size ${pool}) if [[ ! ${histo_pool_size} =~ ${re_number} ]]; then log_fail "histo_pool_size is not numeric ${pool_size}" fi let max_pool_record_size=$(get_prop recordsize ${pool}) if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then log_fail "hptp: max_pool_record_size is not numeric ${max_pool_record_size}" fi sum_filesizes=$(echo "2^21"|bc) ((min_pool_size=12*sum_filesizes)) if [ ${histo_pool_size} -lt ${min_pool_size} ]; then log_note "hptp: Your pool size ${histo_pool_size}" log_fail "hptp: is less than minimum ${min_pool_size}" fi this_ri=min_rsbits file_num=0 total_count=0 ################### # generate 10% + 20% + 30% + 31% = 91% of the filespace # attempting to use 100% will lead to no space left on device # Heuristic testing showed that 91% was the practical upper # bound on the default 4G zpool (mirrored) that is used in # testing. # # In order to expedite testing, we will only fill 2G (of 4G) # of the test pool. You may want to modify this for # standalone testing. # # In filling only 50% of the pool, we create one object on # each "pass" below to achieve multiple objects per record # size. Creating one file per object would lead to # excessive file creation time. ################### # for pass in 10 20 30 31 # 91% for pass in 20 20 10 # 50% do ((thiscount=(((histo_pool_size*pass)/100)/sum_filesizes))) ((total_count+=thiscount)) for rb in $(seq ${min_rsbits} ${max_rsbits}) do this_rs=$(echo "2^${rb}" | bc) if [ ${this_rs} -gt ${max_pool_record_size} ]; then continue fi if [ ! -d /${pool}/B_${this_rs} ]; then zfs create ${pool}/B_${this_rs} zfs set recordsize=${this_rs} \ ${pool}/B_${this_rs} fi #################### # Create the files in the devices and datasets # of the right size. The files are filled # with random data to defeat the compression # # Note that the dd output is suppressed unless # there are errors #################### dd if=/dev/urandom \ of=/${pool}/B_${this_rs}/file_${filenum} \ bs=${this_rs} count=${thiscount} \ iflag=fullblock 2>&1 | \ grep -ve "records in" -e "records out" -e "bytes.*copied" ((filenum+=1)) done done #################### # Testing showed that on some devices, unless the pool is # synchronized, that the block counts will be below the # anticipated sizes since not all of the blocks will be flushed # to the device. This 'sync' command prevents that from # happening. #################### sync_pool ${pool} } function histo_check_test_pool { if [ $# -ne 1 ]; then log_note "histo_check_test_pool: insufficient parameters" log_fail "hctp: 1 requested $# received" fi typeset pool=$1 set -A recordsizes set -A recordcounts typeset -i rb typeset -i min_rsbits=9 #512 typeset -i max_rsbits=SPA_MAXBLOCKSHIFT+1 typeset -i this_rs typeset -i this_ri typeset -i sum_filesizes=0 let histo_check_pool_size=$(get_pool_prop size ${pool}) if [[ ! ${histo_check_pool_size} =~ ${re_number} ]]; then log_fail "histo_check_pool_size is not numeric ${histo_check_pool_size}" fi let max_pool_record_size=$(get_prop recordsize ${pool}) if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then log_fail "hctp: max_pool_record_size is not numeric ${max_pool_record_size}" fi stripped="${TEST_BASE_DIR}/${pool}_stripped.txt" zdb -Pbbb ${pool} | \ sed -e '1,/^block[ ][ ]*psize[ ][ ]*lsize.*$/d' \ -e '/^size[ ]*Count/d' -e '/^$/,$d' \ > ${stripped} sum_filesizes=$(echo "2^21"|bc) ################### # generate 10% + 20% + 30% + 31% = 91% of the filespace # attempting to use 100% will lead to no space left on device # attempting to use 100% will lead to no space left on device # Heuristic testing showed that 91% was the practical upper # bound on the default 4G zpool (mirrored) that is used in # testing. # # In order to expedite testing, we will only fill 2G (of 4G) # of the test pool. You may want to modify this for # standalone testing. # # In filling only 50% of the pool, we create one object on # each "pass" below to achieve multiple objects per record # size. Creating one file per object would lead to # excessive file creation time. ################### # for pass in 10 20 30 31 # 91% for pass in 20 20 10 # 50% do ((thiscount=(((histo_check_pool_size*pass)/100)/sum_filesizes))) for rb in $(seq ${min_rsbits} ${max_rsbits}) do blksize=$(echo "2^$rb"|bc) if [ $blksize -le $max_pool_record_size ]; then ((recordcounts[$blksize]+=thiscount)) fi done done ################### # compare the above computed counts for blocks against # lsize count. Since some devices have a minimum hardware # blocksize > 512, we cannot compare against the asize count. # E.G., if the HWBlocksize = 4096, then the asize counts for # 512, 1024 and 2048 will be zero and rolled up into the # 4096 blocksize count for asize. For verification we stick # to just lsize counts. # - # The max_variance is hard-coded here at 12% to leave us some - # margin. Testing has shown this normally to be in the range - # of 2%-8%, but it may be as large as 11%. + # Variances are expected since this test does not account for + # metadata. The hardcoded limit here is empirical and should + # not be construed as deterministic. ################### - let max_variance=12 + let max_variance=15 let fail_value=0 let error_count=0 log_note "Comparisons for ${pool}" log_note "Bsize is the blocksize, Count is predicted value" log_note "Bsize\tCount\tpsize\tlsize\tasize" while read -r blksize pc pl pm lc ll lm ac al am do if [ $blksize -gt $max_pool_record_size ]; then continue fi log_note \ "$blksize\t${recordcounts[${blksize}]}\t$pc\t$lc\t$ac" ################### # get the computer record count and compute the # difference percentage in integer arithmetic ################### rc=${recordcounts[${blksize}]} ((rclc=(rc-lc)<0?lc-rc:rc-lc)) # absolute value ((dp=(rclc*100)/rc)) ################### # Check against the allowed variance ################### if [ $dp -gt ${max_variance} ]; then log_note \ "Expected variance < ${max_variance}% observed ${dp}%" if [ ${dp} -gt ${fail_value} ]; then fail_value=${dp} ((error_count++)) fi fi done < ${stripped} rm "${stripped}" if [ ${fail_value} -gt 0 ]; then if [ ${error_count} -eq 1 ]; then log_note "hctp: There was ${error_count} error" else log_note "hctp:There were a total of ${error_count} errors" fi log_fail \ "hctp: Max variance of ${max_variance}% exceeded, saw ${fail_value}%" fi } log_assert "Verify zdb -Pbbb (block histogram) works as expected" log_onexit cleanup verify_runnable "global" verify_disk_count "$DISKS" 2 default_mirror_setup_noexit $DISKS histo_populate_test_pool $TESTPOOL histo_check_test_pool $TESTPOOL log_pass "Histogram for zdb"