| #!/usr/bin/env bash |
| |
| get_devtype() { |
| local typ |
| typ=$(udevadm info --query=property --name="$1" | sed -n 's|^ID_FS_TYPE=||p') |
| if [ -z "$typ" ] ; then |
| typ=$(blkid -c /dev/null "$1" -o value -s TYPE) |
| fi |
| echo "$typ" |
| } |
| |
| get_pool_devices() { |
| # also present in 99zfssystemd |
| local poolconfigtemp |
| local poolconfigoutput |
| local pooldev |
| local resolved |
| poolconfigtemp="$(mktemp)" |
| if ! @sbindir@/zpool list -v -H -P "$1" > "$poolconfigtemp" 2>&1 ; then |
| poolconfigoutput="$(cat "$poolconfigtemp")" |
| dinfo "zfsexpandknowledge: pool $1 cannot be listed: $poolconfigoutput" |
| else |
| awk -F '\t' '/\t\/dev/ { print $2 }' "$poolconfigtemp" | \ |
| while read -r pooldev ; do |
| if [ -e "$pooldev" ] ; then |
| resolved="$(readlink -f "$pooldev")" |
| dinfo "zfsexpandknowledge: pool $1 has device $pooldev (which resolves to $resolved)" |
| echo "$resolved" |
| fi |
| done |
| fi |
| rm -f "$poolconfigtemp" |
| } |
| |
| find_zfs_block_devices() { |
| local dev |
| local mp |
| local fstype |
| local _ |
| numfields="$(awk '{print NF; exit}' /proc/self/mountinfo)" |
| if [ "$numfields" = "10" ] ; then |
| fields="_ _ _ _ mp _ _ fstype dev _" |
| else |
| fields="_ _ _ _ mp _ _ _ fstype dev _" |
| fi |
| # shellcheck disable=SC2086 |
| while read -r ${fields?} ; do |
| [ "$fstype" = "zfs" ] || continue |
| [ "$mp" = "$1" ] && get_pool_devices "${dev%%/*}" |
| done < /proc/self/mountinfo |
| } |
| |
| array_contains () { |
| local e |
| for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done |
| return 1 |
| } |
| |
| check() { |
| # https://github.com/dracutdevs/dracut/pull/1711 provides a zfs_devs |
| # function to detect the physical devices backing zfs pools. If this |
| # function exists in the version of dracut this module is being called |
| # from, then it does not need to run. |
| type zfs_devs >/dev/null 2>&1 && return 1 |
| |
| local mp |
| local dev |
| local blockdevs |
| local fstype |
| local majmin |
| local _depdev |
| local _depdevname |
| local _depdevtype |
| |
| # shellcheck disable=SC2154 |
| if [ -n "$hostonly" ]; then |
| |
| for mp in \ |
| "/" \ |
| "/etc" \ |
| "/bin" \ |
| "/sbin" \ |
| "/lib" \ |
| "/lib64" \ |
| "/usr" \ |
| "/usr/bin" \ |
| "/usr/sbin" \ |
| "/usr/lib" \ |
| "/usr/lib64" \ |
| "/boot"; |
| do |
| mp=$(readlink -f "$mp") |
| mountpoint "$mp" >/dev/null 2>&1 || continue |
| blockdevs=$(find_zfs_block_devices "$mp") |
| if [ -z "$blockdevs" ] ; then continue ; fi |
| dinfo "zfsexpandknowledge: block devices backing ZFS dataset $mp: ${blockdevs//$'\n'/ }" |
| for dev in $blockdevs |
| do |
| array_contains "$dev" "${host_devs[@]}" || host_devs+=("$dev") |
| fstype=$(get_devtype "$dev") |
| host_fs_types["$dev"]="$fstype" |
| majmin=$(get_maj_min "$dev") |
| if [ -d "/sys/dev/block/$majmin/slaves" ] ; then |
| for _depdev in "/sys/dev/block/$majmin/slaves"/*; do |
| [ -f "$_depdev/dev" ] || continue |
| _depdev="/dev/${_depdev##*/}" |
| _depdevname=$(udevadm info --query=property --name="$_depdev" | sed -n 's|^DEVNAME=||p') |
| _depdevtype=$(get_devtype "$_depdevname") |
| dinfo "zfsexpandknowledge: underlying block device backing ZFS dataset $mp: ${_depdevname//$'\n'/ }" |
| array_contains "$_depdevname" "${host_devs[@]}" || host_devs+=("$_depdevname") |
| host_fs_types["$_depdevname"]="$_depdevtype" |
| done |
| fi |
| done |
| done |
| for a in "${host_devs[@]}" |
| do |
| dinfo "zfsexpandknowledge: host device $a" |
| done |
| for a in "${!host_fs_types[@]}" |
| do |
| dinfo "zfsexpandknowledge: device $a of type ${host_fs_types[$a]}" |
| done |
| |
| fi |
| |
| return 1 |
| } |