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) 2019 by Datto, Inc. All rights reserved.
16#
17
18. $STF_SUITE/include/libtest.shlib
19
20#
21# Description:
22# zdb -R pool <DVA>:d will display the correct data and length
23#
24# Strategy:
25# 1. Create a pool, set compression to lzjb
26# 2. Write some identifiable data to a file
27# 3. Run zdb -ddddddbbbbbb against the file
28# 4. Record the DVA, lsize, and psize of L0 block 0
29# 5. Run zdb -R with :d flag and match the data
30# 6. Run zdb -R with :dr flags and match the lsize/psize
31# 7. Run zdb -R with :dr flags and match the lsize
32# 8. Run zdb -R with :dr flags and match the psize
33#
34
35
36function cleanup
37{
38	datasetexists $TESTPOOL && destroy_pool $TESTPOOL
39}
40
41log_assert "Verify zdb -R :d flag (decompress) works as expected"
42log_onexit cleanup
43init_data=$TESTDIR/file1
44write_count=256
45blksize=4096
46pattern="_match__pattern_"
47verify_runnable "global"
48verify_disk_count "$DISKS" 2
49
50default_mirror_setup_noexit $DISKS
51log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS
52log_must zfs set compression=lzjb $TESTPOOL/$TESTFS
53
54# 16 chars 256 times = 4k = block size
55typeset four_k=""
56for i in {1..$write_count}
57do
58	four_k=$four_k$pattern
59done
60
61# write the 4k block 256 times
62for i in {1..$write_count}
63do
64	echo $four_k >> $init_data
65done
66
67sync_pool $TESTPOOL true
68
69# get object number of file
70listing=$(ls -i $init_data)
71set -A array $listing
72obj=${array[0]}
73log_note "file $init_data has object number $obj"
74
75output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \
76    |grep -m 1 "L0 DVA")
77dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*$/\1/p' <<< "$output")
78log_note "block 0 of $init_data has a DVA of $dva"
79
80# use the length reported by zdb -ddddddbbbbbb
81size_str=$(sed -Ene 's/^.+ size=([^ ]+) .*$/\1/p' <<< "$output")
82log_note "block size $size_str"
83
84IFS=: read -r vdev offset _ <<< "$dva"
85output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:d)
86echo $output | grep -q $pattern || log_fail "zdb -R :d failed to decompress the data properly"
87
88output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:dr)
89echo $output | grep -q $four_k || log_fail "zdb -R :dr failed to decompress the data properly"
90
91output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:dr)
92result=${#output}
93(( $result != $blksize)) && log_fail \
94"zdb -R failed to decompress the data to the length (${#output} != $size_str)"
95
96# decompress using lsize
97IFS=/ read -r lsize psize _ <<< "$size_str"
98output=$(zdb -R $TESTPOOL $vdev:$offset:$lsize:dr)
99result=${#output}
100(( $result != $blksize)) && log_fail \
101"zdb -R failed to decompress the data (length ${#output} != $blksize)"
102
103# Specifying psize will decompress successfully , but not always to full
104# lsize since zdb has to guess lsize incrementally.
105output=$(zdb -R $TESTPOOL $vdev:$offset:$psize:dr)
106result=${#output}
107# convert psize to decimal
108psize_orig=$psize
109psize=${psize%?}
110psize=$((16#$psize))
111(( $result < $psize)) && log_fail \
112"zdb -R failed to decompress the data with psize $psize_orig\
113 (length ${#output} < $psize)"
114
115log_pass "zdb -R :d flag (decompress) works as expected"
116