From dc3b976f3393d7a3fb75b349418fc8ee2c9142bd Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Wed, 10 Nov 2021 10:19:14 +0100 Subject: [PATCH] fix(dracut-functions.sh): get block device driver if in a virtual subsystem dracut does not install the kernel module of the block device that contains the root filesystem if the following preconditions are met: - Running in host-only mode. - Symlinks of all block devices needed to boot the system pointing to virtual subsystems. The get_dev_module function uses "udevadm info -a" to get the corresponding kernel modules of a /sys/class/*/* or /dev/* device. This function is called in modules.d/90kernel-modules/module-setup.sh to detect if dracut must install block device drivers in host-only mode. The symlinks in /sys/dev/block/ usually point to "real" devices in /sys/devices/pci*. But, we have come across some NVMe systems where the kernel creates the symlinks in /sys/dev/block/ pointing to "virtual" devices instead. In this case, udevadm never finds any "driver" attributes following up the chain of parent devices. --- dracut-functions.sh | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/dracut-functions.sh b/dracut-functions.sh index 3217799482..63b6c892d4 100755 --- a/dracut-functions.sh +++ b/dracut-functions.sh @@ -945,5 +945,29 @@ block_is_netdevice() { # get the corresponding kernel modules of a /sys/class/*/* or/dev/* device get_dev_module() { - udevadm info -a "$1" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' + local dev_attr_walk + local dev_drivers + dev_attr_walk=$(udevadm info -a "$1") + dev_drivers=$(echo "$dev_attr_walk" | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p') + # if no kernel modules found and device is in a virtual subsystem, follow symlinks + if [[ -z $dev_drivers && $(udevadm info -q path "$1") == "/devices/virtual"* ]]; then + local dev_vkernel + local dev_vsubsystem + local dev_vpath + dev_vkernel=$(echo "$dev_attr_walk" | sed -n 's/\s*KERNELS=="\(\S\+\)"/\1/p' | tail -1) + dev_vsubsystem=$(echo "$dev_attr_walk" | sed -n 's/\s*SUBSYSTEMS=="\(\S\+\)"/\1/p' | tail -1) + dev_vpath="/sys/devices/virtual/$dev_vsubsystem/$dev_vkernel" + if [[ -n $dev_vkernel && -n $dev_vsubsystem && -d $dev_vpath ]]; then + local dev_links + local dev_link + dev_links=$(find "$dev_vpath" -maxdepth 1 -type l ! -name "subsystem" -exec readlink {} \;) + for dev_link in $dev_links; do + [[ -n $dev_drivers && ${dev_drivers: -1} != $'\n' ]] && dev_drivers+=$'\n' + dev_drivers+=$(udevadm info -a "$dev_vpath/$dev_link" \ + | sed -n 's/\s*DRIVERS=="\(\S\+\)"/\1/p' \ + | grep -v -e pcieport) + done + fi + fi + echo "$dev_drivers" }