|
| 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) 2016-2018, Allan Jude [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 | + |
| 38 | +function cleanup |
| 39 | +{ |
| 40 | + datasetexists $TESTPOOL && destroy_pool $TESTPOOL |
| 41 | +} |
| 42 | + |
| 43 | +log_assert "Verify zdb -Z (read ZSTD header) works as expected" |
| 44 | +log_onexit cleanup |
| 45 | +src_data=$STF_SUITE/tests/functional/cli_root/zdb/zstd_test_data.txt |
| 46 | +init_data=$TESTDIR/file1 |
| 47 | +write_count=128 |
| 48 | +blksize=131072 |
| 49 | +verify_runnable "global" |
| 50 | +verify_disk_count "$DISKS" 2 |
| 51 | +random_level=$((RANDOM%19 + 1)) |
| 52 | + |
| 53 | +default_mirror_setup_noexit $DISKS |
| 54 | +log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS |
| 55 | +log_must zfs set compression=zstd-$random_level $TESTPOOL/$TESTFS |
| 56 | + |
| 57 | +# write the 1k of text 128 times |
| 58 | +for i in {1..$write_count} |
| 59 | +do |
| 60 | + cat $src_data >> $init_data |
| 61 | +done |
| 62 | + |
| 63 | +sync_pool $TESTPOOL true |
| 64 | + |
| 65 | +# get object number of file |
| 66 | +listing=$(ls -i $init_data) |
| 67 | +set -A array $listing |
| 68 | +obj=${array[0]} |
| 69 | +log_note "file $init_data has object number $obj" |
| 70 | + |
| 71 | +output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \ |
| 72 | + |grep -m 1 "L0 DVA" |head -n1) |
| 73 | +dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output") |
| 74 | +log_note "block 0 of $init_data has a DVA of $dva" |
| 75 | + |
| 76 | +# use the length reported by zdb -ddddddbbbbbb |
| 77 | +size_str=$(sed -Ene 's/^.+ size=([^ ]+) .*$/\1/p' <<< "$output") |
| 78 | +# convert sizes to decimal |
| 79 | +lsize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[1]}') |
| 80 | +lsize_orig=$lsize |
| 81 | +lsize=${lsize%?} |
| 82 | +lsize_bytes=$((16#$lsize)) |
| 83 | +psize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[2]}') |
| 84 | +psize_orig=$psize |
| 85 | +psize=${psize%?} |
| 86 | +psize_bytes=$((16#$psize)) |
| 87 | +log_note "block size $size_str" |
| 88 | + |
| 89 | +# Get the ZSTD header reported by zdb -Z |
| 90 | +zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output") |
| 91 | +zstd_size=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}') |
| 92 | +log_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 | + |
| 96 | +zstd_version=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}') |
| 97 | +log_note "ZSTD version $zstd_version" |
| 98 | + |
| 99 | +zstd_level=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}') |
| 100 | +log_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 | + |
| 104 | +vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}') |
| 105 | +offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}') |
| 106 | +# Check the first 1024 bytes |
| 107 | +output=$(ZDB_NO_ZLE="true" zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null) |
| 108 | +outsize=$(wc -c <<< "$output") |
| 109 | +(( $outsize != $blksize )) && log_fail \ |
| 110 | +"zdb -Z failed to decompress the data to the expected length ($outsize != $lsize_bytes)" |
| 111 | +cmp $init_data - <<< "$output" |
| 112 | +(( $? != 0 )) && log_fail "zdb -R :dr failed to decompress the data properly" |
| 113 | + |
| 114 | +log_pass "zdb -Z flag (ZSTD compression header) works as expected" |
0 commit comments