From 697811ff58c3dfa62fad86e9fe8c9dd7268cadfa Mon Sep 17 00:00:00 2001 From: Pingfan Liu Date: Wed, 28 Jul 2021 18:13:43 +0800 Subject: [PATCH] fix(kernel-modules): detect block device's hardware driver On hostonly mode, the platform driver is not copied blindless. There should be a way to detect the real hardware driver, which probes a block device. /sys/dev/block/major:minor is a symbol link, which points to the real device, recording the hardware stack. And those info can help to identify the associated drivers for the hardware stack. Signed-off-by: Pingfan Liu --- v2 -> v3: address shellcheck in dracut-functions.sh v1 -> v2: remove local variable _extra_mod shorten subject (cherry picked from commit c86f4d286000d1e76fd405560b4114537e2cbbff) Resolves: #1981251 --- dracut-functions.sh | 21 +++++++++++++++++++++ modules.d/90kernel-modules/module-setup.sh | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/dracut-functions.sh b/dracut-functions.sh index 5206bd21..32177994 100755 --- a/dracut-functions.sh +++ b/dracut-functions.sh @@ -617,6 +617,27 @@ for_each_host_dev_and_slaves() { return 1 } +# /sys/dev/block/major:minor is symbol link to real hardware device +# go downstream $(realpath /sys/dev/block/major:minor) to detect driver +get_blockdev_drv_through_sys() { + local _block_mods="" + local _path + + _path=$(realpath "$1") + while true; do + if [[ -L "$_path"/driver/module ]]; then + _mod=$(realpath "$_path"/driver/module) + _mod=$(basename "$_mod") + _block_mods="$_block_mods $_mod" + fi + _path=$(dirname "$_path") + if [[ $_path == '/sys/devices' ]] || [[ $_path == '/' ]]; then + break + fi + done + echo "$_block_mods" +} + # ugly workaround for the lvm design # There is no volume group device, # so, there are no slave devices for volume groups. diff --git a/modules.d/90kernel-modules/module-setup.sh b/modules.d/90kernel-modules/module-setup.sh index 36f8ca3c..86e281ae 100755 --- a/modules.d/90kernel-modules/module-setup.sh +++ b/modules.d/90kernel-modules/module-setup.sh @@ -16,9 +16,15 @@ installkernel() { } record_block_dev_drv() { + for _mod in $(get_dev_module /dev/block/"$1"); do _hostonly_drvs["$_mod"]="$_mod" done + + for _mod in $(get_blockdev_drv_through_sys "/sys/dev/block/$1"); do + _hostonly_drvs["$_mod"]="$_mod" + done + ((${#_hostonly_drvs[@]} > 0)) && return 0 return 1 }