@@ -586,20 +586,37 @@ function list_file_blocks # input_file
586
586
# two are converted to decimal in the while loop. 4M is added to
587
587
# the offset to compensate for the first two labels and boot
588
588
# block. Lastly, the offset and length are printed in units of
589
- # 512b blocks for ease of use with dd.
589
+ # 512B blocks for ease of use with dd.
590
590
#
591
+ typeset level vdev path offset length
592
+ if awk -n '' 2>/dev/null; then
593
+ # gawk needs -n to decode hex
594
+ AWK='awk -n'
595
+ else
596
+ AWK='awk'
597
+ fi
591
598
log_must zpool sync -f
592
- typeset level path offset length
593
- zdb -ddddd $ds $objnum | awk -F: '
599
+ zdb -dddddd $ds $objnum | $AWK -v pad=$((4<<20)) -v bs=512 '
600
+ /^$/ { looking = 0 }
601
+ looking {
602
+ level = $2
603
+ field = 3
604
+ while (split($field, dva, ":") == 3) {
605
+ # top level vdev id
606
+ vdev = int(dva[1])
607
+ # offset + 4M label/boot pad in 512B blocks
608
+ offset = (int("0x"dva[2]) + pad) / bs
609
+ # length in 512B blocks
610
+ len = int("0x"dva[3]) / bs
611
+
612
+ print level, vdev, offset, len
613
+
614
+ ++field
615
+ }
616
+ }
594
617
/^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' | \
618
+ ' | \
598
619
while read level vdev offset length; do
599
- offset=$((16#$offset)) # Conversion from hex
600
- length=$((16#$length))
601
- offset="$(((offset + 4 * 1024 * 1024) / 512))"
602
- length="$((length / 512))"
603
620
for path in ${VDEV_MAP[$vdev][@]}; do
604
621
echo "$level $path $offset $length"
605
622
done
0 commit comments