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# Copyright (c) 2020 Lawrence Livermore National Security, LLC. 17 18. $STF_SUITE/include/libtest.shlib 19 20# 21# Description: 22# Object range parameters passed to zdb -dd work correctly. 23# 24# Strategy: 25# 1. Create a pool 26# 2. Create some files 27# 3. Run zdb -dd with assorted object range arguments and verify output 28 29function cleanup 30{ 31 datasetexists $TESTPOOL && destroy_pool $TESTPOOL 32} 33 34# 35# Print objects in @dataset with identifiers greater than or equal to 36# @begin and less than or equal to @end, without using object range 37# parameters. 38# 39function get_object_list_range 40{ 41 dataset=$1 42 begin=$2 43 end=$3 44 get_object_list $dataset | 45 while read -r line; do 46 read -r obj _ <<<"$line" 47 if [[ $obj -ge $begin && $obj -le $end ]] ; then 48 echo "$line" 49 elif [[ $obj -gt $end ]] ; then 50 break 51 fi 52 done 53} 54 55# 56# Print just the list of objects from 'zdb -dd' with leading whitespace 57# trimmed, discarding other zdb output, sorted by object identifier. 58# Caller must pass in the dataset argument at minimum. 59# 60function get_object_list 61{ 62 zdb -P -dd $@ 2>/dev/null | 63 sed -E '/^ +-?([0-9]+ +){7}/!d;s/^[[:space:]]*//' | 64 sort -n 65} 66 67log_assert "Verify zdb -dd object range arguments work correctly." 68log_onexit cleanup 69verify_runnable "both" 70verify_disk_count "$DISKS" 2 71default_mirror_setup_noexit $DISKS 72 73for x in $(seq 0 7); do 74 touch $TESTDIR/file$x 75 mkdir $TESTDIR/dir$x 76done 77 78sync_all_pools 79 80# Get list of all objects, but filter out user/group objects which don't 81# appear when using object or object range arguments 82all_objects=$(get_object_list $TESTPOOL/$TESTFS | grep -v 'used$') 83 84# Range 0:-1 gets all objects 85expected=$all_objects 86actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1) 87log_must test "\n$actual\n" == "\n$expected\n" 88 89# Range 0:-1:A gets all objects 90expected=$all_objects 91actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:A) 92log_must test "\n$actual\n" == "\n$expected\n" 93 94# Range 0:-1:f must output all file objects 95expected=$(grep "ZFS plain file" <<< $all_objects) 96actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:f) 97log_must test "\n$actual\n" == "\n$expected\n" 98 99# Range 0:-1:d must output all directory objects 100expected=$(grep "ZFS directory" <<< $all_objects) 101actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:d) 102log_must test "\n$actual\n" == "\n$expected\n" 103 104# Range 0:-1:df must output all directory and file objects 105expected=$(grep -e "ZFS directory" -e "ZFS plain file" <<< $all_objects) 106actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:df) 107log_must test "\n$actual\n" == "\n$expected\n" 108 109# Range 0:-1:A-f-d must output all non-files and non-directories 110expected=$(grep -v -e "ZFS plain file" -e "ZFS directory" <<< $all_objects) 111actual=$(get_object_list $TESTPOOL/$TESTFS 0:-1:A-f-d) 112log_must test "\n$actual\n" == "\n$expected\n" 113 114# Specifying multiple ranges works 115set -A obj_ids $(ls -i $TESTDIR | awk '{print $1}' | sort -n) 116start1=${obj_ids[0]} 117end1=${obj_ids[5]} 118start2=${obj_ids[8]} 119end2=${obj_ids[13]} 120expected=$(get_object_list_range $TESTPOOL/$TESTFS $start1 $end1; 121 get_object_list_range $TESTPOOL/$TESTFS $start2 $end2) 122actual=$(get_object_list $TESTPOOL/$TESTFS $start1:$end1 $start2:$end2) 123log_must test "\n$actual\n" == "\n$expected\n" 124 125# Combining ranges with individual object IDs works 126expected=$(get_object_list_range $TESTPOOL/$TESTFS $start1 $end1; 127 get_object_list $TESTPOOL/$TESTFS $start2 $end2) 128actual=$(get_object_list $TESTPOOL/$TESTFS $start1:$end1 $start2 $end2) 129log_must test "\n$actual\n" == "\n$expected\n" 130 131# Hex conversion must work for ranges and individual object identifiers 132# (this test uses expected result from previous test). 133start1_hex=$(printf "0x%x" $start1) 134end1_hex=$(printf "0x%x" $end1) 135start2_hex=$(printf "0x%x" $start2) 136end2_hex=$(printf "0x%x" $end2) 137actual=$(get_object_list $TESTPOOL/$TESTFS $start1_hex:$end1_hex \ 138 $start2_hex $end2_hex) 139log_must test "\n$actual\n" == "\n$expected\n" 140 141# Specifying individual object IDs works 142objects="$start1 $end1 $start2 $end2" 143expected="$objects" 144actual=$(get_object_list $TESTPOOL/$TESTFS $objects | awk '{printf("%s ", $1)}' | tr '\n' ' ') 145log_must test "${actual% }" == "$expected" 146 147# Get all objects in the meta-objset to test m (spacemap) and z (zap) flags 148all_mos_objects=$(get_object_list $TESTPOOL 0:-1) 149 150# Range 0:-1:m must output all space map objects 151expected=$(grep "SPA space map" <<< $all_mos_objects) 152actual=$(get_object_list $TESTPOOL 0:-1:m) 153log_must test "\n$actual\n" == "\n$expected\n" 154 155# Range 0:-1:z must output all zap objects 156expected=$(grep "zap" <<< $all_mos_objects) 157actual=$(get_object_list $TESTPOOL 0:-1:z) 158log_must test "\n$actual\n" == "\n$expected\n" 159 160# Range 0:-1:A-m-z must output all non-space maps and non-zaps 161expected=$(grep -v -e "zap" -e "SPA space map" <<< $all_mos_objects) 162actual=$(get_object_list $TESTPOOL 0:-1:A-m-z) 163log_must test "\n$actual\n" == "\n$expected\n" 164 165# Range 0:-1:mz must output all space maps and zaps 166expected=$(grep -e "SPA space map" -e "zap" <<< $all_mos_objects) 167actual=$(get_object_list $TESTPOOL 0:-1:mz) 168log_must test "\n$actual\n" == "\n$expected\n" 169 170log_pass "zdb -dd object range arguments work correctly" 171