1#!/bin/ksh 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) 2020 The FreeBSD Foundation [1] 16# 17# [1] Portions of this software were developed by Allan Jude 18# under sponsorship from the FreeBSD Foundation. 19 20. $STF_SUITE/include/libtest.shlib 21 22# 23# Description: 24# zdb -Z pool <objid> will display the ZSTD compression header 25# This will contain the actual length of the compressed data, as well as 26# the version of ZSTD used to compress the block, and the compression level 27# 28# Strategy: 29# 1. Create a pool, set compression to zstd-<random level> 30# 2. Write some identifiable data to a file 31# 3. Run zdb -Zddddddbbbbbb against the file 32# 4. Record the DVA, lsize, and psize, and ZSTD header of L0 block 0 33# 5. Check that the ZSTD length is less than psize 34# 6. Check that the ZSTD level matches the level we requested 35# 7. Run zdb -R with :dr flags and confirm the size and content match 36# 37 38function cleanup 39{ 40 datasetexists $TESTPOOL && destroy_pool $TESTPOOL 41} 42 43log_assert "Verify zdb -Z (read ZSTD header) works as expected" 44log_onexit cleanup 45src_data="$STF_SUITE/tests/functional/cli_root/zfs_receive/zstd_test_data.txt" 46init_data=$TESTDIR/file1 47write_count=128 48blksize=131072 49verify_runnable "global" 50verify_disk_count "$DISKS" 2 51random_level=$((RANDOM%19 + 1)) 52 53default_mirror_setup_noexit $DISKS 54log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS 55log_must zfs set compression=zstd-$random_level $TESTPOOL/$TESTFS 56 57# write the 1k of text 128 times 58for i in {1..$write_count} 59do 60 cat $src_data >> $init_data 61done 62 63sync_pool $TESTPOOL true 64 65# get object number of file 66listing=$(ls -i $init_data) 67set -A array $listing 68obj=${array[0]} 69log_note "file $init_data has object number $obj" 70 71output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \ 72 |grep -m 1 "L0 DVA" |head -n1) 73dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output") 74log_note "block 0 of $init_data has a DVA of $dva" 75 76# use the length reported by zdb -ddddddbbbbbb 77size_str=$(sed -Ene 's/^.+ size=([^ ]+) .*$/\1/p' <<< "$output") 78# convert sizes to decimal 79lsize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[1]}') 80lsize_orig=$lsize 81lsize=${lsize%?} 82lsize_bytes=$((16#$lsize)) 83psize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[2]}') 84psize_orig=$psize 85psize=${psize%?} 86psize_bytes=$((16#$psize)) 87log_note "block size $size_str" 88 89# Get the ZSTD header reported by zdb -Z 90zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output") 91zstd_size=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}') 92log_note "ZSTD compressed size $zstd_size" 93(( $psize_bytes < $zstd_size )) && log_fail \ 94"zdb -Z failed: physical block size was less than header content length ($psize_bytes < $zstd_size)" 95 96zstd_version=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}') 97log_note "ZSTD version $zstd_version" 98 99zstd_level=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}') 100log_note "ZSTD level $zstd_level" 101(( $zstd_level != $random_level )) && log_fail \ 102"zdb -Z failed: compression level did not match header level ($zstd_level < $random_level)" 103 104vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}') 105offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}') 106# Check the first 1024 bytes 107output=$(ZDB_NO_ZLE="true" zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null) 108outsize=$(wc -c <<< "$output") 109(( $outsize != $blksize )) && log_fail \ 110"zdb -Z failed to decompress the data to the expected length ($outsize != $lsize_bytes)" 111cmp $init_data - <<< "$output" 112(( $? != 0 )) && log_fail "zdb -R :dr failed to decompress the data properly" 113 114log_pass "zdb -Z flag (ZSTD compression header) works as expected" 115