Skip to content

Commit 3b0564f

Browse files
Ryan Moellerjsai20
authored andcommitted
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 openzfs#11141
1 parent e3098d3 commit 3b0564f

File tree

1 file changed

+37
-21
lines changed

1 file changed

+37
-21
lines changed

tests/zfs-tests/include/blkdev.shlib

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -548,22 +548,37 @@ function list_file_blocks # input_file
548548

549549
#
550550
# Establish a mapping between vdev ids as shown in a DVA and the
551-
# pathnames they correspond to in ${VDEV_MAP[]}.
551+
# pathnames they correspond to in ${VDEV_MAP[][]}.
552+
#
553+
# The vdev bits in a DVA refer to the top level vdev id.
554+
# ${VDEV_MAP[$id]} is an array of the vdev paths within that vdev.
552555
#
553556
eval $(zdb -C $pool | awk '
554-
BEGIN {
555-
printf("typeset VDEV_MAP\n");
556-
looking = 0;
557-
}
558-
/^ children/ {
559-
id = $1;
560-
looking = 1;
561-
}
562-
/path: / && looking == 1 {
563-
print id" "$2;
564-
looking = 0;
565-
}
566-
' | sed -n 's/^children\[\([0-9]\)\]: \(.*\)$/VDEV_MAP[\1]=\2/p')
557+
BEGIN { printf "typeset -a VDEV_MAP;" }
558+
function subscript(s) {
559+
# "[#]" is more convenient than the bare "#"
560+
match(s, /\[[0-9]*\]/)
561+
return substr(s, RSTART, RLENGTH)
562+
}
563+
id && !/^ / {
564+
# left a top level vdev
565+
id = 0
566+
}
567+
id && $1 ~ /^path:$/ {
568+
# found a vdev path; save it in the map
569+
printf "VDEV_MAP%s%s=%s;", id, child, $2
570+
}
571+
/^ children/ {
572+
# entering a top level vdev
573+
id = subscript($0)
574+
child = "[0]" # default in case there is no nested vdev
575+
printf "typeset -a VDEV_MAP%s;", id
576+
}
577+
/^ children/ {
578+
# entering a nested vdev (e.g. child of a top level mirror)
579+
child = subscript($0)
580+
}
581+
')
567582

568583
#
569584
# The awk below parses the output of zdb, printing out the level
@@ -576,17 +591,18 @@ function list_file_blocks # input_file
576591
log_must zpool sync -f
577592
typeset level path offset length
578593
zdb -ddddd $ds $objnum | awk -F: '
579-
BEGIN { looking = 0 }
580-
/^Indirect blocks:/ { looking = 1}
581-
/^\t\tsegment / { looking = 0}
582-
/L[0-8]/ && looking == 1 { print $0}
583-
' | sed -n 's/^.*\(L[0-9]\) \([0-9]*\):\([0-9a-f]*\):\([0-9a-f]*\) .*$/\1 \2 \3 \4/p' | \
584-
while read level path offset length; do
594+
/^Indirect blocks:/ { looking = 1 }
595+
/^\t\tsegment / { looking = 0 }
596+
/L[0-8]/ && looking { print }
597+
' | sed -n 's/^.*\(L[0-9]\) *\([0-9]*\):\([0-9a-f]*\):\([0-9a-f]*\) .*$/\1 \2 \3 \4/p' | \
598+
while read level vdev offset length; do
585599
offset=$((16#$offset)) # Conversion from hex
586600
length=$((16#$length))
587601
offset="$(((offset + 4 * 1024 * 1024) / 512))"
588602
length="$((length / 512))"
589-
echo "$level ${VDEV_MAP[$path]} $offset $length"
603+
for path in ${VDEV_MAP[$vdev][@]}; do
604+
echo "$level $path $offset $length"
605+
done
590606
done 2>/dev/null
591607
}
592608

0 commit comments

Comments
 (0)