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 <behlendorf1@llnl.gov> Signed-off-by: Ryan Moeller <ryan@iXsystems.com> Closes #11141
This commit is contained in:
parent
ae37ceadaa
commit
94deb47872
|
@ -548,22 +548,37 @@ function list_file_blocks # input_file
|
||||||
|
|
||||||
#
|
#
|
||||||
# Establish a mapping between vdev ids as shown in a DVA and the
|
# 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 '
|
eval $(zdb -C $pool | awk '
|
||||||
BEGIN {
|
BEGIN { printf "typeset -a VDEV_MAP;" }
|
||||||
printf("typeset VDEV_MAP\n");
|
function subscript(s) {
|
||||||
looking = 0;
|
# "[#]" 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/ {
|
/^ children/ {
|
||||||
id = $1;
|
# entering a top level vdev
|
||||||
looking = 1;
|
id = subscript($0)
|
||||||
|
child = "[0]" # default in case there is no nested vdev
|
||||||
|
printf "typeset -a VDEV_MAP%s;", id
|
||||||
}
|
}
|
||||||
/path: / && looking == 1 {
|
/^ children/ {
|
||||||
print id" "$2;
|
# entering a nested vdev (e.g. child of a top level mirror)
|
||||||
looking = 0;
|
child = subscript($0)
|
||||||
}
|
}
|
||||||
' | sed -n 's/^children\[\([0-9]\)\]: \(.*\)$/VDEV_MAP[\1]=\2/p')
|
')
|
||||||
|
|
||||||
#
|
#
|
||||||
# The awk below parses the output of zdb, printing out the level
|
# 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
|
log_must zpool sync -f
|
||||||
typeset level path offset length
|
typeset level path offset length
|
||||||
zdb -ddddd $ds $objnum | awk -F: '
|
zdb -ddddd $ds $objnum | awk -F: '
|
||||||
BEGIN { looking = 0 }
|
/^Indirect blocks:/ { looking = 1 }
|
||||||
/^Indirect blocks:/ { looking = 1}
|
/^\t\tsegment / { looking = 0 }
|
||||||
/^\t\tsegment / { looking = 0}
|
/L[0-8]/ && looking { print }
|
||||||
/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' | \
|
||||||
' | 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
|
||||||
while read level path offset length; do
|
|
||||||
offset=$((16#$offset)) # Conversion from hex
|
offset=$((16#$offset)) # Conversion from hex
|
||||||
length=$((16#$length))
|
length=$((16#$length))
|
||||||
offset="$(((offset + 4 * 1024 * 1024) / 512))"
|
offset="$(((offset + 4 * 1024 * 1024) / 512))"
|
||||||
length="$((length / 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
|
done 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue