diff options
Diffstat (limited to 'sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh')
-rwxr-xr-x | sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh new file mode 100755 index 000000000000..238d49560461 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress_zstd.ksh @@ -0,0 +1,114 @@ +#!/bin/ksh + +# +# 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) 2020 The FreeBSD Foundation [1] +# +# [1] Portions of this software were developed by Allan Jude +# under sponsorship from the FreeBSD Foundation. + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -Z pool <objid> will display the ZSTD compression header +# This will contain the actual length of the compressed data, as well as +# the version of ZSTD used to compress the block, and the compression level +# +# Strategy: +# 1. Create a pool, set compression to zstd-<random level> +# 2. Write some identifiable data to a file +# 3. Run zdb -Zddddddbbbbbb against the file +# 4. Record the DVA, lsize, and psize, and ZSTD header of L0 block 0 +# 5. Check that the ZSTD length is less than psize +# 6. Check that the ZSTD level matches the level we requested +# 7. Run zdb -R with :dr flags and confirm the size and content match +# + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_assert "Verify zdb -Z (read ZSTD header) works as expected" +log_onexit cleanup +src_data="$STF_SUITE/tests/functional/cli_root/zfs_receive/zstd_test_data.txt" +init_data=$TESTDIR/file1 +write_count=128 +blksize=131072 +verify_runnable "global" +verify_disk_count "$DISKS" 2 +random_level=$((RANDOM%19 + 1)) + +default_mirror_setup_noexit $DISKS +log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS +log_must zfs set compression=zstd-$random_level $TESTPOOL/$TESTFS + +# write the 1k of text 128 times +for i in {1..$write_count} +do + cat $src_data >> $init_data +done + +sync_pool $TESTPOOL true + +# get object number of file +listing=$(ls -i $init_data) +set -A array $listing +obj=${array[0]} +log_note "file $init_data has object number $obj" + +output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \ + |grep -m 1 "L0 DVA" |head -n1) +dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output") +log_note "block 0 of $init_data has a DVA of $dva" + +# use the length reported by zdb -ddddddbbbbbb +size_str=$(sed -Ene 's/^.+ size=([^ ]+) .*$/\1/p' <<< "$output") +# convert sizes to decimal +lsize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[1]}') +lsize_orig=$lsize +lsize=${lsize%?} +lsize_bytes=$((16#$lsize)) +psize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[2]}') +psize_orig=$psize +psize=${psize%?} +psize_bytes=$((16#$psize)) +log_note "block size $size_str" + +# Get the ZSTD header reported by zdb -Z +zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output") +zstd_size=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}') +log_note "ZSTD compressed size $zstd_size" +(( $psize_bytes < $zstd_size )) && log_fail \ +"zdb -Z failed: physical block size was less than header content length ($psize_bytes < $zstd_size)" + +zstd_version=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}') +log_note "ZSTD version $zstd_version" + +zstd_level=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}') +log_note "ZSTD level $zstd_level" +(( $zstd_level != $random_level )) && log_fail \ +"zdb -Z failed: compression level did not match header level ($zstd_level < $random_level)" + +vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}') +offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}') +# Check the first 1024 bytes +output=$(ZDB_NO_ZLE="true" zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null) +outsize=$(wc -c <<< "$output") +(( $outsize != $blksize )) && log_fail \ +"zdb -Z failed to decompress the data to the expected length ($outsize != $lsize_bytes)" +cmp $init_data - <<< "$output" +(( $? != 0 )) && log_fail "zdb -R :dr failed to decompress the data properly" + +log_pass "zdb -Z flag (ZSTD compression header) works as expected" |