1#!/bin/ksh -p 2# 3# CDDL HEADER START 4# 5# This file and its contents are supplied under the terms of the 6# Common Development and Distribution License ("CDDL"), version 1.0. 7# You may only use this file in accordance with the terms of version 8# 1.0 of the CDDL. 9# 10# A full copy of the text of the CDDL should have accompanied this 11# source. A copy of the CDDL is also available via the Internet at 12# http://www.illumos.org/license/CDDL. 13# 14# CDDL HEADER END 15# 16 17# 18# Copyright (c) 2020 The FreeBSD Foundation [1] 19# 20# [1] Portions of this software were developed by Allan Jude 21# under sponsorship from the FreeBSD Foundation. 22 23. $STF_SUITE/include/libtest.shlib 24 25# 26# DESCRIPTION: 27# ZFS should receive a ZSTD compressed block and be able to determine the level 28# 29# STRATEGY: 30# 1. Create a ZSTD compressed dataset (random level) 31# 2. Create and checksum a file on the compressed dataset 32# 3. Snapshot the compressed dataset 33# 4. Attempt to receive the snapshot into a new dataset 34# 5. Verify the checksum of the file is the same as the original 35# 6. Verify the compression level is correctly stored 36# 37 38verify_runnable "both" 39 40function cleanup 41{ 42 datasetexists $TESTPOOL/$TESTFS1 && \ 43 destroy_dataset $TESTPOOL/$TESTFS1 -r 44 45 datasetexists $TESTPOOL/$TESTFS2 && \ 46 destroy_dataset $TESTPOOL/$TESTFS2 -r 47} 48 49log_onexit cleanup 50 51log_assert "ZFS should track compression level when receiving a ZSTD stream" 52 53typeset src_data="$STF_SUITE/tests/functional/cli_root/zfs_receive/zstd_test_data.txt" 54typeset snap="$TESTPOOL/$TESTFS1@snap" 55 56random_level=$((RANDOM%19 + 1)) 57log_note "Randomly selected ZSTD level: $random_level" 58 59log_must zfs create -o compress=zstd-$random_level $TESTPOOL/$TESTFS1 60# Make a 5kb compressible file 61log_must cat $src_data $src_data $src_data $src_data $src_data \ 62 > /$TESTPOOL/$TESTFS1/$TESTFILE0 63typeset checksum=$(md5digest /$TESTPOOL/$TESTFS1/$TESTFILE0) 64 65log_must zfs snapshot $snap 66 67# get object number of file 68listing=$(ls -i /$TESTPOOL/$TESTFS1/$TESTFILE0) 69set -A array $listing 70obj=${array[0]} 71log_note "file /$TESTPOOL/$TESTFS1/$TESTFILE0 has object number $obj" 72 73output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS1 $obj 2> /dev/null \ 74 |grep -m 1 "L0 DVA" |head -n1) 75dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output") 76log_note "block 0 of /$TESTPOOL/$TESTFS1/$TESTFILE0 has a DVA of $dva" 77 78zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output") 79zstd_size1=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}') 80zstd_version1=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}') 81zstd_level1=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}') 82log_note "ZSTD src: size=$zstd_size1 version=$zstd_version1 level=$zstd_level1" 83 84log_note "Verify ZFS can receive the ZSTD compressed stream" 85log_must eval "zfs send -ec $snap | zfs receive $TESTPOOL/$TESTFS2" 86 87typeset cksum1=$(md5digest /$TESTPOOL/$TESTFS2/$TESTFILE0) 88[[ "$cksum1" == "$checksum" ]] || \ 89 log_fail "Checksums differ ($cksum1 != $checksum)" 90 91# get object number of file 92listing=$(ls -i /$TESTPOOL/$TESTFS2/$TESTFILE0) 93set -A array $listing 94obj=${array[0]} 95log_note "file /$TESTPOOL/$TESTFS2/$TESTFILE0 has object number $obj" 96 97output=$(zdb -Zddddddbbbbbb $TESTPOOL/$TESTFS2 $obj 2> /dev/null \ 98 |grep -m 1 "L0 DVA" |head -n1) 99dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output") 100log_note "block 0 of /$TESTPOOL/$TESTFS2/$TESTFILE0 has a DVA of $dva" 101 102zstd_str=$(sed -Ene 's/^.+ ZSTD:size=([^:]+):version=([^:]+):level=([^:]+):.*$/\1:\2:\3/p' <<< "$output") 103zstd_size2=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[1]}') 104(( $zstd_size2 != $zstd_size1 )) && log_fail \ 105"ZFS recv failed: compressed size differs ($zstd_size2 != $zstd_size1)" 106zstd_version2=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[2]}') 107zstd_level2=$(echo "$zstd_str" |awk '{split($0,array,":")} END{print array[3]}') 108log_note "ZSTD dest: size=$zstd_size2 version=$zstd_version2 level=$zstd_level2" 109(( $zstd_level2 != $zstd_level1 )) && log_fail \ 110"ZFS recv failed: compression level did not match header level ($zstd_level2 != $zstd_level1)" 111 112log_pass "ZFS can receive a ZSTD stream and determine the compression level" 113