#!/bin/sh device() { local out out=$(stat 2>/dev/null -f "%Sp %SZ" -- "$1") case $out in b*) out=${out#* } out=${out#*,} out=${out%[^0-9]} ;; c*) out=${out#* r} out=${out%%,*} out=${out%[^0-9]} ;; *) out="$1" ;; esac echo "$out" } raid() { raidctl -G "$1" \ | sed \ -e '1,/^START disks/d' \ -e 's,^ *,,' \ -e '/^$/,$d' \ | while read p; do device "$p" done } vnd() { vndconfig -l -- "$1" \ | sed \ -e 's,.*(,,' \ -e 's,).*,,' \ | while read p; do device "$p" done } ccd() { ccdconfig -g -- "$1" \ | while read x1 x2 x3 x4 list; do for p in $list; do device "$p" done done } cgd() { cgdconfig -l -- "$1" \ | while read tag p; do device "/dev/$p" done } dk() { dkctl "$1" getwedgeinfo \ | sed \ -e '1s,.*at \(.*\):.*,\1,' \ -e '2,$d' } lvs() { dmsetup 2>/dev/null table -- "$1" \ | while read lo hi typ spec; do case $typ in linear) set -- $spec echo $1 ;; striped) set -- $spec shift 2 while [ $# -gt 1 ]; do echo $1 shift 2 done ;; esac done | while read p; do device "$p" done } zvol() { ( zpool 2>/dev/null list -v -H "${1%/*}" \ || echo " /dev/zvol/dsk" ) | sed -ne 's/^[[:space:]]\([^[:space:]]*\).*/\1/p' \ | while read p; do device "$p" done } for d in $(sysctl -n hw.disknames); do case $d in raid*) set -- $(raid "$d") for c in "$@"; do echo "$c $d" done ;; vnd*) set -- $(vnd "$d") echo "$1 $d" ;; cgd*) t="cgd" set -- $(cgd "$d") echo "$1 $d" ;; ccd*) set -- $(ccd "$d") for c in "$@"; do echo "$c $d" done ;; dk*) set -- $(dk "$d") echo "$1 $d" ;; *) if [ -b "/dev/mapper/$d" ]; then set -- $(lvs "$d") for c in "$@"; do echo "$c $d" done elif [ -b "/dev/zvol/dsk/$d" ]; then set -- $(zvol "$d") for c in "$@"; do echo "$c $d" done else echo "$d" fi ;; esac done | awk ' function disktype(dev, s) { "drvctl 2>/dev/null -p " dev " /disk-info/type | cat -ve" | getline s return s } NF == 1 { depth[$1] = 0 type[$1] = disktype($1) } NF == 2 { d = depth[$1] + 1 if (d > depth[$2]) depth[$2] = d if (depth[$2] > maxdepth) maxdepth = depth[$2] pp="" for (k=1; k<=nparents[$1]; ++k) pp = parents[$1,k] " " pp parents[$2,++nparents[$2]] = pp $1 } END { for (node in depth) { d = depth[node] tree[d,++nchildren[d]] = node } for (d=0; d<=maxdepth; ++d) { for (i=1; i<=nchildren[d]; ++i) { node = tree[d,i] if (nparents[node] > 0) for (k=1; k<=nparents[node]; ++k) print parents[node,k],node else { t = type[node] if (t != "") t = " \"" t "\"" print node t } } } } ' | sort | awk '{ for (i=1; i<=NF; ++i) { if (l[i] != $i) break fmt = "%" length(l[i]) "s%s" sep = i == NF ? "\n" : OFS printf fmt,"",sep } for (; i<=NF; ++i) { l[i] = $i sep = i == NF ? "\n" : OFS printf "%s%s",l[i],sep } }'