diff options
Diffstat (limited to 'sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb')
16 files changed, 1598 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am new file mode 100644 index 000000000000..18420efcb26a --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/Makefile.am @@ -0,0 +1,17 @@ +pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zdb +dist_pkgdata_SCRIPTS = \ + zdb_002_pos.ksh \ + zdb_003_pos.ksh \ + zdb_004_pos.ksh \ + zdb_005_pos.ksh \ + zdb_006_pos.ksh \ + zdb_args_neg.ksh \ + zdb_args_pos.ksh \ + zdb_block_size_histogram.ksh \ + zdb_checksum.ksh \ + zdb_decompress.ksh \ + zdb_decompress_zstd.ksh \ + zdb_object_range_neg.ksh \ + zdb_object_range_pos.ksh \ + zdb_display_block.ksh \ + zdb_objset_id.ksh diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh new file mode 100755 index 000000000000..ec7e1dcab9c9 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_002_pos.ksh @@ -0,0 +1,51 @@ +#!/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) 2015 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb will accurately count the feature refcount for pools with and without +# features enabled. +# +# Strategy: +# 1. Create a pool, and collect zdb output for the pool. +# 2. Verify there are no 'feature refcount mismatch' messages. +# 3. Repeat for a pool with features disabled. +# + +log_assert "Verify zdb accurately counts feature refcounts." +log_onexit cleanup + +typeset errstr="feature refcount mismatch" +typeset tmpfile="$TEST_BASE_DIR/zdb-feature-mismatch" +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + grep "$errstr" $tmpfile + rm -f $tmpfile +} + +for opt in '' -d; do + log_must zpool create -f $opt $TESTPOOL ${DISKS%% *} + log_must eval "zdb $TESTPOOL >$tmpfile" + grep -q "$errstr" $tmpfile && \ + log_fail "Found feature refcount mismatches in zdb output." + destroy_pool $TESTPOOL +done + +log_pass "zdb accurately counts feature refcounts." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh new file mode 100755 index 000000000000..36f1929dd193 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_003_pos.ksh @@ -0,0 +1,72 @@ +#!/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) 2017 by Lawrence Livermore National Security, LLC. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb will not produce redundant dumps of configurations +# +# Strategy: +# 1. Create a pool with two vdevs +# 2. Copy label 1 from the first vdev to the second vdev +# 3. Collect zdb -l output for both vdevs +# 4. Verify that the correct number of configs is dumped for each +# + +log_assert "Verify zdb does not produce redundant dumps of configurations" +log_onexit cleanup + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + if is_freebsd ; then + log_must sysctl kern.geom.debugflags=$saved_debugflags + fi +} + +if is_freebsd ; then + # FreeBSD won't allow writing to an in-use device without this set + saved_debugflags=$(sysctl -n kern.geom.debugflags) + log_must sysctl kern.geom.debugflags=16 +fi + +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +config_count=(1 2) +set -A DISK $DISKS + +default_mirror_setup_noexit $DISKS + +DEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR}) +log_note "$DEVS" +[[ -n $DEVS ]] && set -A DISK $DEVS + +log_must dd if=/dev/${DISK[0]} of=/dev/${DISK[1]} bs=1K count=256 conv=notrunc + +for x in 0 1 ; do + config_count=$(zdb -l $DEV_RDSKDIR/${DISK[$x]} | grep -c features_for_read) + (( $? != 0)) && log_fail "failed to get config_count from DISK[$x]" + log_note "vdev $x: message_count $config_count" + [ $config_count -ne ${config_count[$x]} ] && \ + log_fail "zdb produces an incorrect number of configuration dumps." +done + +cleanup + +log_pass "zdb produces unique dumps of configurations." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh new file mode 100755 index 000000000000..2c6e6e9be070 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_004_pos.ksh @@ -0,0 +1,93 @@ +#!/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) 2017 by Lawrence Livermore National Security, LLC. +# Copyright (c) 2020 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb will not produce redundant dumps of uberblocks +# +# Strategy: +# 1. Create a pool with two vdevs, A and B +# 2. Offline vdev A +# 3. Do some I/O +# 4. Export the pool +# 5. Copy label 1 from vdev A to vdev B +# 6. Collect zdb -lu output for vdev B +# 7. Verify labels 0 and 1 have unique Uberblocks, but 2 and 3 have none +# + +log_assert "Verify zdb produces unique dumps of uberblocks" +log_onexit cleanup + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + for DISK in $DISKS; do + zpool labelclear -f $DEV_RDSKDIR/$DISK + done + if is_freebsd; then + log_must sysctl kern.geom.debugflags=$saved_debugflags + fi +} + +if is_freebsd; then + # FreeBSD won't allow writing to an in-use device without this set + saved_debugflags=$(sysctl -n kern.geom.debugflags) + log_must sysctl kern.geom.debugflags=16 +fi + +verify_runnable "global" +verify_disk_count "$DISKS" 2 +set -A DISK $DISKS +WHOLE_DISK=${DISK[0]} + +default_mirror_setup_noexit $DISKS +DEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR}) +[[ -n $DEVS ]] && set -A DISK $DEVS + +log_must zpool offline $TESTPOOL $WHOLE_DISK +log_must dd if=/dev/urandom of=$TESTDIR/testfile bs=1K count=2 +log_must zpool export $TESTPOOL + +log_must dd if=$DEV_RDSKDIR/${DISK[0]} of=$DEV_RDSKDIR/${DISK[1]} bs=1K count=256 conv=notrunc + +ubs=$(zdb -lu ${DISK[1]} | grep -e LABEL -e Uberblock -e 'labels = ') +log_note "vdev 1: ubs $ubs" + +ub_dump_counts=$(zdb -lu ${DISK[1]} | \ + awk ' /LABEL/ {label=$NF; blocks[label]=0}; + /Uberblock/ {blocks[label]++}; + END {print blocks[0],blocks[1],blocks[2],blocks[3]}') +(( $? != 0)) && log_fail "failed to get ub_dump_counts from DISK[1]" +log_note "vdev 1: ub_dump_counts $ub_dump_counts" + +set -A dump_count $ub_dump_counts +for label in 0 1 2 3; do + if [[ $label -lt 2 ]]; then + [[ ${dump_count[$label]} -eq 0 ]] && \ + log_fail "zdb incorrectly dumps duplicate uberblocks" + else + [[ ${dump_count[$label]} -ne 0 ]] && \ + log_fail "zdb incorrectly dumps duplicate uberblocks" + fi +done + +cleanup + +log_pass "zdb produces unique dumps of uberblocks" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh new file mode 100755 index 000000000000..74975dbb0dde --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_005_pos.ksh @@ -0,0 +1,78 @@ +#!/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) 2017 by Lawrence Livermore National Security, LLC. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -l exit codes are correct +# +# Strategy: +# 1. Create a pool +# 2. Overwrite label 0 on vdev[1] with dd +# 3. Create an empty file +# 3. Run zdb -l on vdev[0] and verify exit value 0 +# 4. Run zdb -l on vdev[1] and verify exit value 1 +# 5. Run zdb -l on the empty file and verify exit value 2 +# + +log_assert "Verify zdb -l exit codes are correct" +log_onexit cleanup + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + rm -f $TEMPFILE + if is_freebsd ; then + log_must sysctl kern.geom.debugflags=$saved_debugflags + fi +} + +if is_freebsd ; then + # FreeBSD won't allow writing to an in-use device without this set + saved_debugflags=$(sysctl -n kern.geom.debugflags) + log_must sysctl kern.geom.debugflags=16 +fi + +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +set -A DISK $DISKS + +default_mirror_setup_noexit $DISKS +DEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR}) +log_note "$DEVS" +[[ -n $DEVS ]] && set -A DISK $DEVS + +log_must dd if=/dev/zero of=$DEV_RDSKDIR/${DISK[1]} bs=1K count=256 conv=notrunc +log_must truncate -s 0 $TEMPFILE + +zdb -l $DEV_RDSKDIR/${DISK[0]} +[[ $? -ne 0 ]] && + log_fail "zdb -l exit codes are incorrect." + +zdb -l $DEV_RDSKDIR/${DISK[1]} +[[ $? -ne 1 ]] && + log_fail "zdb -l exit codes are incorrect." + +zdb -l $TEMPFILE +[[ $? -ne 2 ]] && + log_fail "zdb -l exit codes are incorrect." + +cleanup + +log_pass "zdb -l exit codes are correct." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh new file mode 100755 index 000000000000..97b00e9e1996 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_006_pos.ksh @@ -0,0 +1,64 @@ +#!/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) 2018 by Nutanix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -d will work on imported/exported pool with pool/dataset argument +# +# Strategy: +# 1. Create a pool +# 2. Run zdb -d with pool and dataset arguments. +# 3. Export the pool +# 4. Run zdb -ed with pool and dataset arguments. +# + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL + for DISK in $DISKS; do + zpool labelclear -f $DEV_RDSKDIR/$DISK + done +} + +log_assert "Verify zdb -d works on imported/exported pool with pool/dataset argument" +log_onexit cleanup + +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +log_must zfs snap $TESTPOOL/$TESTFS@snap + +log_must zdb -d $TESTPOOL +log_must zdb -d $TESTPOOL/ +log_must zdb -d $TESTPOOL/$TESTFS +log_must zdb -d $TESTPOOL/$TESTFS@snap + +log_must zpool export $TESTPOOL + +log_must zdb -ed $TESTPOOL +log_must zdb -ed $TESTPOOL/ +log_must zdb -ed $TESTPOOL/$TESTFS +log_must zdb -ed $TESTPOOL/$TESTFS@snap + +log_must zpool import $TESTPOOL + +cleanup + +log_pass "zdb -d works on imported/exported pool with pool/dataset argument" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh new file mode 100755 index 000000000000..1b0219780adc --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_neg.ksh @@ -0,0 +1,83 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2012, 2017 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# A badly formed parameter passed to zdb(1) should +# return an error. +# +# STRATEGY: +# 1. Create an array containing bad zdb parameters. +# 2. For each element, execute the sub-command. +# 3. Verify it returns an error. +# + +verify_runnable "global" + +set -A args "create" "add" "destroy" "import fakepool" \ + "export fakepool" "create fakepool" "add fakepool" \ + "create mirror" "create raidz" \ + "create mirror fakepool" "create raidz fakepool" \ + "create raidz1 fakepool" "create raidz2 fakepool" \ + "create fakepool mirror" "create fakepool raidz" \ + "create fakepool raidz1" "create fakepool raidz2" \ + "add fakepool mirror" "add fakepool raidz" \ + "add fakepool raidz1" "add fakepool raidz2" \ + "add mirror fakepool" "add raidz fakepool" \ + "add raidz1 fakepool" "add raidz2 fakepool" \ + "setvprop" "blah blah" "-%" "--?" "-*" "-=" \ + "-a" "-f" "-g" "-j" "-n" "-o" "-p" "-p /tmp" "-r" \ + "-t" "-w" "-z" "-E" "-H" "-I" "-J" "-K" \ + "-N" "-Q" "-R" "-T" "-W" + +log_assert "Execute zdb using invalid parameters." + +log_onexit cleanup + +function cleanup +{ + default_cleanup_noexit +} + +function test_imported_pool +{ + for i in ${args[@]}; do + log_mustnot zdb $i $TESTPOOL + done +} + +default_mirror_setup_noexit $DISKS + +test_imported_pool + +log_pass "Badly formed zdb parameters fail as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh new file mode 100755 index 000000000000..4c2fc15ec025 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_args_pos.ksh @@ -0,0 +1,104 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2012, 2020 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# ZDB allows a large number of possible inputs +# and combinations of those inputs. Test for non-zero +# exit values. These input options are based on the zdb +# man page +# +# STRATEGY: +# 1. Create an array containing value zdb parameters. +# 2. For each element, execute the sub-command. +# 3. Verify it does not return a error. +# + +verify_runnable "global" + +log_assert "Execute zdb using valid parameters." + +log_onexit cleanup + +function cleanup +{ + default_cleanup_noexit +} + +function test_imported_pool +{ + typeset -a args=("-A" "-b" "-C" "-c" "-d" "-D" "-G" "-h" "-i" "-L" \ + "-M" "-P" "-s" "-v" "-Y" "-y") + for i in ${args[@]}; do + log_must eval "zdb $i $TESTPOOL >/dev/null" + done +} + +function test_exported_pool +{ + log_must zpool export $TESTPOOL + typeset -a args=("-A" "-b" "-C" "-c" "-d" "-D" "-F" "-G" "-h" "-i" "-L" "-M" \ + "-P" "-s" "-v" "-X" "-Y" "-y") + for i in ${args[@]}; do + log_must eval "zdb -e $i $TESTPOOL >/dev/null" + done + log_must zpool import $TESTPOOL +} + +function test_vdev +{ + typeset -a args=("-A" "-q" "-u" "-Aqu") + VDEVS=$(get_pool_devices ${TESTPOOL} ${DEV_RDSKDIR}) + log_note $VDEVS + set -A VDEV_ARRAY $VDEVS + for i in ${args[@]}; do + log_must eval "zdb -l $i ${VDEV_ARRAY[0]} >/dev/null" + done +} + +function test_metaslab +{ + typeset -a args=("-A" "-L" "-P" "-Y") + for i in ${args[@]}; do + log_must eval "zdb -m $i $TESTPOOL >/dev/null" + done +} + +default_mirror_setup_noexit $DISKS + +test_imported_pool +test_exported_pool +test_vdev +test_metaslab + +log_pass "Valid zdb parameters pass as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh new file mode 100755 index 000000000000..0c949f9839e1 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_block_size_histogram.ksh @@ -0,0 +1,272 @@ +#!/bin/ksh -p + +# +# 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) 2017 by Delphix. All rights reserved. +# Copyright (c) 2020 by Lawrence Livermore National Security LLC. + +. $STF_SUITE/include/libtest.shlib + + +# +# DESCRIPTION: +# Create a pool and populate it with files of various +# recordsizes +# +# STRATEGY: +# 1. Create pool +# 2. Populate it +# 3. Run zdb -Pbbb on pool +# 4. Verify variance on blocksizes +# +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +SPA_MAXBLOCKSHIFT=24 + +function histo_populate_test_pool +{ + if [ $# -ne 1 ]; then + log_note "histo_populate_test_pool: insufficient parameters" + log_fail "hptp: 1 requested $# received" + fi + typeset pool=$1 + + set -A recordsizes + typeset -i min_rsbits=9 #512 + typeset -i max_rsbits=SPA_MAXBLOCKSHIFT #16 MiB + typeset -i sum_filesizes=0 + re_number='^[0-9]+$' + + let histo_pool_size=$(get_pool_prop size ${pool}) + if [[ ! ${histo_pool_size} =~ ${re_number} ]]; then + log_fail "histo_pool_size is not numeric ${pool_size}" + fi + let max_pool_record_size=$(get_prop recordsize ${pool}) + if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then + log_fail "hptp: max_pool_record_size is not numeric ${max_pool_record_size}" + fi + + sum_filesizes=$(echo "2^21"|bc) + ((min_pool_size=12*sum_filesizes)) + if [ ${histo_pool_size} -lt ${min_pool_size} ]; then + log_note "hptp: Your pool size ${histo_pool_size}" + log_fail "hptp: is less than minimum ${min_pool_size}" + fi + this_ri=min_rsbits + file_num=0 + total_count=0 + ################### + # generate 10% + 20% + 30% + 31% = 91% of the filespace + # attempting to use 100% will lead to no space left on device + # Heuristic testing showed that 91% was the practical upper + # bound on the default 4G zpool (mirrored) that is used in + # testing. + # + # In order to expedite testing, we will only fill 2G (of 4G) + # of the test pool. You may want to modify this for + # standalone testing. + # + # In filling only 50% of the pool, we create one object on + # each "pass" below to achieve multiple objects per record + # size. Creating one file per object would lead to + # excessive file creation time. + ################### + # for pass in 10 20 30 31 # 91% + for pass in 20 20 10 # 50% + do + ((thiscount=(((histo_pool_size*pass)/100)/sum_filesizes))) + + ((total_count+=thiscount)) + for rb in $(seq ${min_rsbits} ${max_rsbits}) + do + this_rs=$(echo "2^${rb}" | bc) + if [ ${this_rs} -gt ${max_pool_record_size} ]; then + continue + fi + + if [ ! -d /${pool}/B_${this_rs} ]; then + zfs create ${pool}/B_${this_rs} + zfs set recordsize=${this_rs} \ + ${pool}/B_${this_rs} + fi + #################### + # Create the files in the devices and datasets + # of the right size. The files are filled + # with random data to defeat the compression + # + # Note that the dd output is suppressed unless + # there are errors + #################### + + dd if=/dev/urandom \ + of=/${pool}/B_${this_rs}/file_${filenum} \ + bs=${this_rs} count=${thiscount} \ + iflag=fullblock 2>&1 | \ + egrep -v -e "records in" -e "records out" \ + -e "bytes.*copied" + ((filenum+=1)) + done + done + + #################### + # Testing showed that on some devices, unless the pool is + # synchronized, that the block counts will be below the + # anticipated sizes since not all of the blocks will be flushed + # to the device. This 'sync' command prevents that from + # happening. + #################### + log_must zpool sync ${pool} +} +function histo_check_test_pool +{ + if [ $# -ne 1 ]; then + log_note "histo_check_test_pool: insufficient parameters" + log_fail "hctp: 1 requested $# received" + fi + typeset pool=$1 + + set -A recordsizes + set -A recordcounts + typeset -i rb + typeset -i min_rsbits=9 #512 + typeset -i max_rsbits=SPA_MAXBLOCKSHIFT+1 + typeset -i this_rs + typeset -i this_ri + typeset -i sum_filesizes=0 + typeset dumped + typeset stripped + + let histo_check_pool_size=$(get_pool_prop size ${pool}) + if [[ ! ${histo_check_pool_size} =~ ${re_number} ]]; then + log_fail "histo_check_pool_size is not numeric ${histo_check_pool_size}" + fi + let max_pool_record_size=$(get_prop recordsize ${pool}) + if [[ ! ${max_pool_record_size} =~ ${re_number} ]]; then + log_fail "hctp: max_pool_record_size is not numeric ${max_pool_record_size}" + fi + + dumped="${TEST_BASE_DIR}/${pool}_dump.txt" + stripped="${TEST_BASE_DIR}/${pool}_stripped.txt" + + zdb -Pbbb ${pool} | \ + tee ${dumped} | \ + sed -e '1,/^block[ ][ ]*psize[ ][ ]*lsize.*$/d' \ + -e '/^size[ ]*Count/d' -e '/^$/,$d' \ + > ${stripped} + + sum_filesizes=$(echo "2^21"|bc) + + ################### + # generate 10% + 20% + 30% + 31% = 91% of the filespace + # attempting to use 100% will lead to no space left on device + # attempting to use 100% will lead to no space left on device + # Heuristic testing showed that 91% was the practical upper + # bound on the default 4G zpool (mirrored) that is used in + # testing. + # + # In order to expedite testing, we will only fill 2G (of 4G) + # of the test pool. You may want to modify this for + # standalone testing. + # + # In filling only 50% of the pool, we create one object on + # each "pass" below to achieve multiple objects per record + # size. Creating one file per object would lead to + # excessive file creation time. + ################### + # for pass in 10 20 30 31 # 91% + for pass in 20 20 10 # 50% + do + ((thiscount=(((histo_check_pool_size*pass)/100)/sum_filesizes))) + + for rb in $(seq ${min_rsbits} ${max_rsbits}) + do + blksize=$(echo "2^$rb"|bc) + if [ $blksize -le $max_pool_record_size ]; then + ((recordcounts[$blksize]+=thiscount)) + fi + done + done + + ################### + # compare the above computed counts for blocks against + # lsize count. Since some devices have a minimum hardware + # blocksize > 512, we cannot compare against the asize count. + # E.G., if the HWBlocksize = 4096, then the asize counts for + # 512, 1024 and 2048 will be zero and rolled up into the + # 4096 blocksize count for asize. For verification we stick + # to just lsize counts. + # + # The max_variance is hard-coded here at 10%. testing so far + # has shown this to be in the range of 2%-8% so we leave a + # generous allowance... This might need changes in the future + ################### + let max_variance=10 + let fail_value=0 + let error_count=0 + log_note "Comparisons for ${pool}" + log_note "Bsize is the blocksize, Count is predicted value" + log_note "Bsize\tCount\tpsize\tlsize\tasize" + while read -r blksize pc pl pm lc ll lm ac al am + do + if [ $blksize -gt $max_pool_record_size ]; then + continue + fi + log_note \ + "$blksize\t${recordcounts[${blksize}]}\t$pc\t$lc\t$ac" + + ################### + # get the computer record count and compute the + # difference percentage in integer arithmetic + ################### + rc=${recordcounts[${blksize}]} + ((rclc=(rc-lc)<0?lc-rc:rc-lc)) # absolute value + ((dp=(rclc*100)/rc)) + + ################### + # Check against the allowed variance + ################### + if [ $dp -gt ${max_variance} ]; then + log_note \ + "Expected variance < ${max_variance}% observed ${dp}%" + if [ ${dp} -gt ${fail_value} ]; then + fail_value=${dp} + ((error_count++)) + fi + fi + done < ${stripped} + if [ ${fail_value} -gt 0 ]; then + if [ ${error_count} -eq 1 ]; then + log_note "hctp: There was ${error_count} error" + else + log_note "hctp:There were a total of ${error_count} errors" + fi + log_fail \ + "hctp: Max variance of ${max_variance}% exceeded, saw ${fail_value}%" + fi +} + +log_assert "Verify zdb -Pbbb (block histogram) works as expected" +log_onexit cleanup +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS + +histo_populate_test_pool $TESTPOOL + +histo_check_test_pool $TESTPOOL + +log_pass "Histogram for zdb" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh new file mode 100755 index 000000000000..eeff6575f0f4 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_checksum.ksh @@ -0,0 +1,64 @@ +#!/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) 2019 by Datto, Inc. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -c will display the same checksum as -ddddddbbbbbb +# +# Strategy: +# 1. Create a pool +# 2. Write some data to a file +# 3. Run zdb -ddddddbbbbbb against the file +# 4. Record the checksum and DVA of L0 block 0 +# 5. Run zdb -R with :c flag and match the checksum + + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_assert "Verify zdb -R generates the correct checksum." +log_onexit cleanup +init_data=$TESTDIR/file1 +write_count=8 +blksize=131072 +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +file_write -o create -w -f $init_data -b $blksize -c $write_count + +# 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 -ddddddbbbbbb $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" +cksum_expected=$(sed -Ene 's/^.+ cksum=([a-z0-9:]+)$/\1/p' <<< "$output") +log_note "expecting cksum $cksum_expected" +output=$(zdb -R $TESTPOOL $dva:c 2> /dev/null) +result=$(grep $cksum_expected <<< "$output") +(( $? != 0 )) && log_fail "zdb -R failed to print the correct checksum" + +log_pass "zdb -R generates the correct checksum" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh new file mode 100755 index 000000000000..1ebcbfb44953 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_decompress.ksh @@ -0,0 +1,119 @@ +#!/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) 2019 by Datto, Inc. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -R pool <DVA>:d will display the correct data and length +# +# Strategy: +# 1. Create a pool, set compression to lzjb +# 2. Write some identifiable data to a file +# 3. Run zdb -ddddddbbbbbb against the file +# 4. Record the DVA, lsize, and psize of L0 block 0 +# 5. Run zdb -R with :d flag and match the data +# 6. Run zdb -R with :dr flags and match the lsize/psize +# 7. Run zdb -R with :dr flags and match the lsize +# 8. Run zdb -R with :dr flags and match the psize +# + + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_assert "Verify zdb -R :d flag (decompress) works as expected" +log_onexit cleanup +init_data=$TESTDIR/file1 +write_count=256 +blksize=4096 +pattern="_match__pattern_" +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS +log_must zfs set compression=lzjb $TESTPOOL/$TESTFS + +# 16 chars 256 times = 4k = block size +typeset four_k="" +for i in {1..$write_count} +do + four_k=$four_k$pattern +done + +# write the 4k block 256 times +for i in {1..$write_count} +do + echo $four_k >> $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 -ddddddbbbbbb $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") +log_note "block size $size_str" + +vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}') +offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}') +output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:d 2> /dev/null) +echo $output |grep $pattern > /dev/null +(( $? != 0 )) && log_fail "zdb -R :d failed to decompress the data properly" + +output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null) +echo $output |grep $four_k > /dev/null +(( $? != 0 )) && log_fail "zdb -R :dr failed to decompress the data properly" + +output=$(zdb -R $TESTPOOL $vdev:$offset:$size_str:dr 2> /dev/null) +result=${#output} +(( $result != $blksize)) && log_fail \ +"zdb -R failed to decompress the data to the length (${#output} != $size_str)" + +# decompress using lsize +lsize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[1]}') +psize=$(echo $size_str |awk '{split($0,array,"/")} END{print array[2]}') +output=$(zdb -R $TESTPOOL $vdev:$offset:$lsize:dr 2> /dev/null) +result=${#output} +(( $result != $blksize)) && log_fail \ +"zdb -R failed to decompress the data (length ${#output} != $blksize)" + +# Specifying psize will decompress successfully , but not always to full +# lsize since zdb has to guess lsize incrementally. +output=$(zdb -R $TESTPOOL $vdev:$offset:$psize:dr 2> /dev/null) +result=${#output} +# convert psize to decimal +psize_orig=$psize +psize=${psize%?} +psize=$((16#$psize)) +(( $result < $psize)) && log_fail \ +"zdb -R failed to decompress the data with psize $psize_orig\ + (length ${#output} < $psize)" + +log_pass "zdb -R :d flag (decompress) works as expected" 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" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh new file mode 100755 index 000000000000..5cc4575851f7 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_display_block.ksh @@ -0,0 +1,128 @@ +#!/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) 2019 by Datto, Inc. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -R pool <DVA>:b will display the block +# +# Strategy: +# 1. Create a pool, set compression to lzjb +# 2. Write some identifiable data to a file +# 3. Run zdb -ddddddbbbbbb against the file +# 4. Record the DVA of the first L1 block; +# record the first L0 block display; and +# record the 2nd L0 block display. +# 5. Run zdb -R with :bd displays first L0 +# 6. Run zdb -R with :b80d displays 2nd L0 +# 7. Run zdb -R with :db80 displays 2nd L0 +# 8. Run zdb -R with :id flag displays indirect block +# (similar to zdb -ddddddbbbbbb output) +# 9. Run zdb -R with :id flag and .0 vdev +# + + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_assert "Verify zdb -R :b flag (block display) works as expected" +log_onexit cleanup +init_data=$TESTDIR/file1 +write_count=256 +blksize=4096 + +# only read 256 128 byte block pointers in L1 (:i flag) +# 256 x 128 = 32k / 0x8000 +l1_read_size="8000" + +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +log_must zfs set recordsize=$blksize $TESTPOOL/$TESTFS +log_must zfs set compression=lzjb $TESTPOOL/$TESTFS + +file_write -d R -o create -w -f $init_data -b $blksize -c $write_count +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 -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \ + |grep -m 1 "L1 DVA" |head -n1) +dva=$(sed -Ene 's/^.+DVA\[0\]=<([^>]+)>.*/\1/p' <<< "$output") +log_note "first L1 block $init_data has a DVA of $dva" +output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \ + |grep -m 1 "L0 DVA" |head -n1) +blk_out0=${output##*>} +blk_out0=${blk_out0##+([[:space:]])} + +output=$(zdb -ddddddbbbbbb $TESTPOOL/$TESTFS $obj 2> /dev/null \ + |grep -m 1 "1000 L0 DVA" |head -n1) +blk_out1=${output##*>} +blk_out1=${blk_out1##+([[:space:]])} + +output=$(export ZDB_NO_ZLE=\"true\"; zdb -R $TESTPOOL $dva:bd\ + 2> /dev/null) +output=${output##*>} +output=${output##+([[:space:]])} +if [ "$output" != "$blk_out0" ]; then + log_fail "zdb -R :bd (block 0 display/decompress) failed" +fi + +output=$(export ZDB_NO_ZLE=\"true\"; zdb -R $TESTPOOL $dva:db80\ + 2> /dev/null) +output=${output##*>} +output=${output##+([[:space:]])} +if [ "$output" != "$blk_out1" ]; then + log_fail "zdb -R :db80 (block 1 display/decompress) failed" +fi + +output=$(export ZDB_NO_ZLE=\"true\"; zdb -R $TESTPOOL $dva:b80d\ + 2> /dev/null) +output=${output##*>} +output=${output##+([[:space:]])} +if [ "$output" != "$blk_out1" ]; then + log_fail "zdb -R :b80d (block 1 display/decompress) failed" +fi + +vdev=$(echo "$dva" |awk '{split($0,array,":")} END{print array[1]}') +offset=$(echo "$dva" |awk '{split($0,array,":")} END{print array[2]}') +output=$(export ZDB_NO_ZLE=\"true\";\ + zdb -R $TESTPOOL $vdev:$offset:$l1_read_size:id 2> /dev/null) +block_cnt=$(echo "$output" | grep 'L0' | wc -l) +if [ $block_cnt -ne $write_count ]; then + log_fail "zdb -R :id (indirect block display) failed" +fi + +# read from specific half of mirror +vdev="$vdev.0" +log_note "Reading from DVA $vdev:$offset:$l1_read_size" +output=$(export ZDB_NO_ZLE=\"true\";\ + zdb -R $TESTPOOL $vdev:$offset:$l1_read_size:id 2> /dev/null) +block_cnt=$(echo "$output" | grep 'L0' | wc -l) +if [ $block_cnt -ne $write_count ]; then + log_fail "zdb -R 0.0:offset:length:id (indirect block display) failed" +fi + +log_pass "zdb -R :b flag (block display) works as expected" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh new file mode 100755 index 000000000000..430180788044 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_neg.ksh @@ -0,0 +1,72 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# 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. +# +# CDDL HEADER END +# +# Copyright (c) 2020 Lawrence Livermore National Security, LLC. + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# A badly formed object range parameter passed to zdb -dd should +# return an error. +# +# Strategy: +# 1. Create a pool +# 2. Run zdb -dd with assorted invalid object range arguments and +# confirm it fails as expected +# 3. Run zdb -dd with an invalid object identifier and +# confirm it fails as expected + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_assert "Execute zdb using invalid object range parameters." +log_onexit cleanup +verify_runnable "both" +verify_disk_count "$DISKS" 2 +default_mirror_setup_noexit $DISKS + +log_must zpool sync + +set -A bad_flags a b c e g h i j k l n o p q r s t u v w x y \ + B C D E F G H I J K L M N O P Q R S T U V W X Y Z \ + 0 1 2 3 4 5 6 7 8 9 _ - + % . , : + +typeset -i i=0 +while [[ $i -lt ${#bad_flags[*]} ]]; do + log_mustnot zdb -dd $TESTPOOL 0:1:${bad_flags[i]} + log_mustnot zdb -dd $TESTPOOL 0:1:A-${bad_flags[i]} + ((i = i + 1)) +done + +set -A bad_ranges ":" "::" ":::" ":0" "0:" "0:1:" "0:1::" "0::f" "0a:1" \ + "a0:1" "a:1" "0:a" "0:1a" "0:a1" "a:b0" "a:0b" "0:1:A-" "1:0" \ + "0:1:f:f" "0:1:f:" + +i=0 +while [[ $i -lt ${#bad_ranges[*]} ]]; do + log_mustnot zdb -dd $TESTPOOL ${bad_ranges[i]} + ((i = i + 1)) +done + +# Specifying a non-existent object identifier returns an error +obj_id_highest=$(zdb -P -dd $TESTPOOL/$TESTFS 2>/dev/null | + egrep "^ +-?([0-9]+ +){7}" | sort -n | tail -n 1 | awk '{print $1}') +obj_id_invalid=$(( $obj_id_highest + 1 )) +log_mustnot zdb -dd $TESTPOOL/$TESTFS $obj_id_invalid + +log_pass "Badly formed zdb object range parameters fail as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh new file mode 100755 index 000000000000..b7f47d11ad2f --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_object_range_pos.ksh @@ -0,0 +1,171 @@ +#!/bin/ksh -p +# +# CDDL HEADER START +# +# 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. +# +# CDDL HEADER END +# +# Copyright (c) 2020 Lawrence Livermore National Security, LLC. + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# Object range parameters passed to zdb -dd work correctly. +# +# Strategy: +# 1. Create a pool +# 2. Create some files +# 3. Run zdb -dd with assorted object range arguments and verify output + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +# +# Print objects in @dataset with identifiers greater than or equal to +# @begin and less than or equal to @end, without using object range +# parameters. +# +function get_object_list_range +{ + dataset=$1 + begin=$2 + end=$3 + get_object_list $dataset | + while read line; do + obj=$(echo $line | awk '{print $1}') + if [[ $obj -ge $begin && $obj -le $end ]] ; then + echo "$line" + elif [[ $obj -gt $end ]] ; then + break + fi + done +} + +# +# Print just the list of objects from 'zdb -dd' with leading whitespace +# trimmed, discarding other zdb output, sorted by object identifier. +# Caller must pass in the dataset argument at minimum. +# +function get_object_list +{ + zdb -P -dd $@ 2>/dev/null | + egrep "^ +-?([0-9]+ +){7}" | + sed 's/^[[:space:]]*//' | + sort -n +} + +log_assert "Verify zdb -dd object range arguments work correctly." +log_onexit cleanup +verify_runnable "both" +verify_disk_count "$DISKS" 2 +default_mirror_setup_noexit $DISKS + +for x in $(seq 0 7); do + touch $TESTDIR/file$x + mkdir $TESTDIR/dir$x +done + +log_must zpool sync + +# Get list of all objects, but filter out user/group objects which don't +# appear when using object or object range arguments +all_objects=$(get_object_list $TESTPOOL/$TESTFS | grep -v 'used$') + +# Range 0:-1 gets all objects +expected=$all_objects +actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:A gets all objects +expected=$all_objects +actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:A) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:f must output all file objects +expected=$(grep "ZFS plain file" <<< $all_objects) +actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:f) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:d must output all directory objects +expected=$(grep "ZFS directory" <<< $all_objects) +actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:d) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:df must output all directory and file objects +expected=$(grep -e "ZFS directory" -e "ZFS plain file" <<< $all_objects) +actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:df) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:A-f-d must output all non-files and non-directories +expected=$(grep -v -e "ZFS plain file" -e "ZFS directory" <<< $all_objects) +actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:A-f-d) +log_must test "\n$actual\n" == "\n$expected\n" + +# Specifying multiple ranges works +set -A obj_ids $(ls -i $TESTDIR | awk '{print $1}' | sort -n) +start1=${obj_ids[0]} +end1=${obj_ids[5]} +start2=${obj_ids[8]} +end2=${obj_ids[13]} +expected=$(get_object_list_range $TESTPOOL/$TESTFS $start1 $end1; + get_object_list_range $TESTPOOL/$TESTFS $start2 $end2) +actual=$(get_object_list $TESTPOOL/$TESTFS $start1:$end1 $start2:$end2) +log_must test "\n$actual\n" == "\n$expected\n" + +# Combining ranges with individual object IDs works +expected=$(get_object_list_range $TESTPOOL/$TESTFS $start1 $end1; + get_object_list $TESTPOOL/$TESTFS $start2 $end2) +actual=$(get_object_list $TESTPOOL/$TESTFS $start1:$end1 $start2 $end2) +log_must test "\n$actual\n" == "\n$expected\n" + +# Hex conversion must work for ranges and individual object identifiers +# (this test uses expected result from previous test). +start1_hex=$(printf "0x%x" $start1) +end1_hex=$(printf "0x%x" $end1) +start2_hex=$(printf "0x%x" $start2) +end2_hex=$(printf "0x%x" $end2) +actual=$(get_object_list $TESTPOOL/$TESTFS $start1_hex:$end1_hex \ + $start2_hex $end2_hex) +log_must test "\n$actual\n" == "\n$expected\n" + +# Specifying individual object IDs works +objects="$start1 $end1 $start2 $end2" +expected="$objects" +actual=$(get_object_list $TESTPOOL/$TESTFS $objects | awk '{print $1}' | xargs) +log_must test "$actual" == "$expected" + +# Get all objects in the meta-objset to test m (spacemap) and z (zap) flags +all_mos_objects=$(get_object_list $TESTPOOL 0:-1) + +# Range 0:-1:m must output all space map objects +expected=$(grep "SPA space map" <<< $all_mos_objects) +actual=$(get_object_list $TESTPOOL 0:-1:m) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:z must output all zap objects +expected=$(grep "zap" <<< $all_mos_objects) +actual=$(get_object_list $TESTPOOL 0:-1:z) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:A-m-z must output all non-space maps and non-zaps +expected=$(grep -v -e "zap" -e "SPA space map" <<< $all_mos_objects) +actual=$(get_object_list $TESTPOOL 0:-1:A-m-z) +log_must test "\n$actual\n" == "\n$expected\n" + +# Range 0:-1:mz must output all space maps and zaps +expected=$(grep -e "SPA space map" -e "zap" <<< $all_mos_objects) +actual=$(get_object_list $TESTPOOL 0:-1:mz) +log_must test "\n$actual\n" == "\n$expected\n" + +log_pass "zdb -dd object range arguments work correctly" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh new file mode 100755 index 000000000000..f0c1076c97bd --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_objset_id.ksh @@ -0,0 +1,96 @@ +#!/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 by Datto, Inc. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib + +# +# Description: +# zdb -d pool/<objset id> will display the dataset +# +# Strategy: +# 1. Create a pool +# 2. Write some data to a file +# 3. Get the inode number (object number) of the file +# 4. Run zdb -d to get the objset ID of the dataset +# 5. Run zdb -dddddd pool/objsetID objectID (decimal) +# 6. Confirm names +# 7. Run zdb -dddddd pool/objsetID objectID (hex) +# 8. Confirm names +# 9. Obtain objsetID from /proc/spl/kstat/zfs/testpool/obset-0x<ID> +# (linux only) +# 10. Run zdb -dddddd pool/objsetID (hex) +# 11. Match name from zdb against proc entry +# + +function cleanup +{ + datasetexists $TESTPOOL && destroy_pool $TESTPOOL +} + +log_assert "Verify zdb -d <pool>/<objset ID> generates the correct names." +log_onexit cleanup +init_data=$TESTDIR/file1 +write_count=8 +blksize=131072 +verify_runnable "global" +verify_disk_count "$DISKS" 2 + +default_mirror_setup_noexit $DISKS +file_write -o create -w -f $init_data -b $blksize -c $write_count + +# 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 -d $TESTPOOL/$TESTFS) +objset_id=$(echo $output | awk '{split($0,array,",")} END{print array[2]}' | + awk '{split($0,array," ")} END{print array[2]}') +objset_hex=$(printf "0x%X" $objset_id) +log_note "objset $TESTPOOL/$TESTFS has objset ID $objset_id ($objset_hex)" + +for id in "$objset_id" "$objset_hex" +do + log_note "zdb -dddddd $TESTPOOL/$id $obj" + output=$(zdb -dddddd $TESTPOOL/$id $obj) + reason="($TESTPOOL/$TESTFS not in zdb output)" + echo $output |grep "$TESTPOOL/$TESTFS" > /dev/null + (( $? != 0 )) && log_fail \ + "zdb -dddddd $TESTPOOL/$id $obj failed $reason" + reason="(file1 not in zdb output)" + echo $output |grep "file1" > /dev/null + (( $? != 0 )) && log_fail \ + "zdb -dddddd $TESTPOOL/$id $obj failed $reason" + obj=$(printf "0x%X" $obj) +done + +if is_linux; then + output=$(ls -1 /proc/spl/kstat/zfs/$TESTPOOL |grep objset- |tail -1) + objset_hex=${output#*-} + name_from_proc=$(cat /proc/spl/kstat/zfs/$TESTPOOL/$output | + grep dataset_name | awk '{split($0,array," ")} END{print array[3]}') + log_note "checking zdb output for $name_from_proc" + reason="(name $name_from_proc from proc not in zdb output)" + log_note "zdb -dddddd $TESTPOOL/$objset_hex" + output=$(zdb -dddddd $TESTPOOL/$objset_hex) + echo $output |grep "$name_from_proc" > /dev/null + (( $? != 0 )) && log_fail \ + "zdb -dddddd $TESTPOOL/$objset_hex failed $reason" +fi + +log_pass "zdb -d <pool>/<objset ID> generates the correct names." |