#!/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 }