diff options
author | Ryan Moeller <[email protected]> | 2020-10-28 20:29:31 +0000 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2020-11-05 17:16:16 -0800 |
commit | 94deb47872e1fd6cf460eddf119bd219bcb30a27 (patch) | |
tree | 9c6b1dde973b6e81024e3cdc5813ffac9e7f7ae7 /tests | |
parent | ae37ceadaa2a8cf09fbf1a9baafaa6dc6e24318a (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.shlib | 58 |
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 } |