summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorRyan Moeller <[email protected]>2020-10-28 20:29:31 +0000
committerBrian Behlendorf <[email protected]>2020-11-05 17:16:16 -0800
commit94deb47872e1fd6cf460eddf119bd219bcb30a27 (patch)
tree9c6b1dde973b6e81024e3cdc5813ffac9e7f7ae7 /tests
parentae37ceadaa2a8cf09fbf1a9baafaa6dc6e24318a (diff)
ZTS: Fix list_file_blocks for mirror vdevs, level > 0
The first part of list_file_blocks transforms the pool configuration output by zdb -C $pool into shell code to set up a shell variable, VDEV_MAP, that maps from vdev id to the underlying vdev path. This variable is a simple indexed array. However, the vdev id in a DVA is only the id of the top level vdev. When the pool is mirrored, the top level vdev is a mirror and its children are the mirrored devices. So, what we need is to map from the top level vdev id to a list of the underlying vdev paths. ist_file_blocks does not need to work for raidz vdevs, so we can disregard that case. Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Ryan Moeller <[email protected]> Closes #11141
Diffstat (limited to 'tests')
-rw-r--r--tests/zfs-tests/include/blkdev.shlib58
1 files changed, 37 insertions, 21 deletions
diff --git a/tests/zfs-tests/include/blkdev.shlib b/tests/zfs-tests/include/blkdev.shlib
index b34f2c04d..9522baebd 100644
--- a/tests/zfs-tests/include/blkdev.shlib
+++ b/tests/zfs-tests/include/blkdev.shlib
@@ -548,22 +548,37 @@ function list_file_blocks # input_file
#
# Establish a mapping between vdev ids as shown in a DVA and the
- # pathnames they correspond to in ${VDEV_MAP[]}.
+ # pathnames they correspond to in ${VDEV_MAP[][]}.
+ #
+ # The vdev bits in a DVA refer to the top level vdev id.
+ # ${VDEV_MAP[$id]} is an array of the vdev paths within that vdev.
#
eval $(zdb -C $pool | awk '
- BEGIN {
- printf("typeset VDEV_MAP\n");
- looking = 0;
- }
- /^ children/ {
- id = $1;
- looking = 1;
- }
- /path: / && looking == 1 {
- print id" "$2;
- looking = 0;
- }
- ' | sed -n 's/^children\[\([0-9]\)\]: \(.*\)$/VDEV_MAP[\1]=\2/p')
+ BEGIN { printf "typeset -a VDEV_MAP;" }
+ function subscript(s) {
+ # "[#]" is more convenient than the bare "#"
+ match(s, /\[[0-9]*\]/)
+ return substr(s, RSTART, RLENGTH)
+ }
+ id && !/^ / {
+ # left a top level vdev
+ id = 0
+ }
+ id && $1 ~ /^path:$/ {
+ # found a vdev path; save it in the map
+ printf "VDEV_MAP%s%s=%s;", id, child, $2
+ }
+ /^ children/ {
+ # entering a top level vdev
+ id = subscript($0)
+ child = "[0]" # default in case there is no nested vdev
+ printf "typeset -a VDEV_MAP%s;", id
+ }
+ /^ children/ {
+ # entering a nested vdev (e.g. child of a top level mirror)
+ child = subscript($0)
+ }
+ ')
#
# The awk below parses the output of zdb, printing out the level
@@ -576,17 +591,18 @@ function list_file_blocks # input_file
log_must zpool sync -f
typeset level path offset length
zdb -ddddd $ds $objnum | awk -F: '
- BEGIN { looking = 0 }
- /^Indirect blocks:/ { looking = 1}
- /^\t\tsegment / { looking = 0}
- /L[0-8]/ && looking == 1 { print $0}
- ' | sed -n 's/^.*\(L[0-9]\) \([0-9]*\):\([0-9a-f]*\):\([0-9a-f]*\) .*$/\1 \2 \3 \4/p' | \
- while read level path offset length; do
+ /^Indirect blocks:/ { looking = 1 }
+ /^\t\tsegment / { looking = 0 }
+ /L[0-8]/ && looking { print }
+ ' | sed -n 's/^.*\(L[0-9]\) *\([0-9]*\):\([0-9a-f]*\):\([0-9a-f]*\) .*$/\1 \2 \3 \4/p' | \
+ while read level vdev offset length; do
offset=$((16#$offset)) # Conversion from hex
length=$((16#$length))
offset="$(((offset + 4 * 1024 * 1024) / 512))"
length="$((length / 512))"
- echo "$level ${VDEV_MAP[$path]} $offset $length"
+ for path in ${VDEV_MAP[$vdev][@]}; do
+ echo "$level $path $offset $length"
+ done
done 2>/dev/null
}