From 06a30ae529a5d6ad2369ed81da056bf3a6147bb6 Mon Sep 17 00:00:00 2001 From: Steffen Maier Date: Fri, 20 Jan 2023 17:44:04 +0100 Subject: [PATCH] zdev/dracut: add rd.zfcp cmdline option handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add parsing of dracut cmdline option "rd.zfcp=..." at initrd runtime. It delegates configuration to chzdev. Implement `dracut --print-cmdline` and `dracut --hostonly-cmdline` for initrd build time. Emit an rd.zfcp option for each zfcp-attached SCSI disk in dracut's device dependency graph (to mount the root-fs, or to access the kdump target). This allows a distribution independent device configuration. Configuration is consistent by using chzdev as backend. It also prevents duplicate activations of the same device. Along with the existing functionality of zdev/dracut, it makes the following dracut modules superfluous: https://github.com/dracutdevs/dracut/tree/master/modules.d/95zfcp [rd.zfcp.conf is no longer needed and thus ignored here; the preceding ("zdev/dracut: fix marking hostonly files so delete option works") makes rd.hostonly=0 work as a generic replacement] https://github.com/dracutdevs/dracut/tree/master/modules.d/95zfcp_rules Github-ID: https://github.com/ibm-s390-linux/s390-tools/pull/158 Acked-by: Vineeth Vijayan Acked-by: Peter Oberparleiter Signed-off-by: Steffen Maier Signed-off-by: Jan Höppner --- zdev/dracut/95zdev-kdump/module-setup.sh | 31 +++++++++- zdev/dracut/95zdev/module-setup.sh | 30 +++++++++- zdev/dracut/95zdev/parse-zfcp.sh | 35 +++++++++++ zdev/dracut/95zdev/zdev-lib.sh | 75 ++++++++++++++++++++++++ zdev/dracut/Makefile | 1 + 5 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 zdev/dracut/95zdev/parse-zfcp.sh diff --git a/zdev/dracut/95zdev-kdump/module-setup.sh b/zdev/dracut/95zdev-kdump/module-setup.sh index 7f9a6451..5d7f2172 100755 --- a/zdev/dracut/95zdev-kdump/module-setup.sh +++ b/zdev/dracut/95zdev-kdump/module-setup.sh @@ -8,7 +8,8 @@ # # 95zdev-kdump/module_setup.sh # This module installs configuration files (udev rules and modprobe.conf -# files) required to enable the kdump target on s390. +# files) required to enable the kdump target on s390. In addition, +# a hook is installed to parse rd.zfcp= kernel parameters. # # called by dracut @@ -26,6 +27,7 @@ check() { # Ensure that required tools are available require_binaries chzdev lszdev || return 1 + require_binaries grep sort uniq || return 1 return 0 } @@ -35,6 +37,19 @@ depends() { return 0 } +# called by dracut and (conditionally) locally by install() +# Generate rd.zfcp dracut cmdline options for each zfcp-attached +# SCSI disk in dracut's device dependency graph (to mount the root-fs, +# or to access the kdump target). With "dracut --print-cmdline", dracut +# prints the list. With "dracut --hostonly-cmdline", dracut stores the +# list inside the generated initrd. +cmdline() { + # shellcheck disable=SC2154 + if [[ $hostonly ]]; then + for_each_host_dev_and_slaves_all zdev_check_dev | sort | uniq + fi +} + # called by dracut installkernel() { # Add modules for all device types supported by chzdev (required for @@ -51,8 +66,22 @@ install() { # installing avoids error messages from zdev site udev rule processing inst_multiple -o /lib/s390-tools/zdev_id + # Ensure that required tools are available + inst_multiple chzdev grep + + # Hook to parse zfcp dracut cmdline parameter + inst_hook cmdline 95 "$moddir/../95zdev/parse-zfcp.sh" + # Obtain kdump target device configuration + # shellcheck disable=SC2154 + if [[ $hostonly_cmdline == "yes" ]]; then + local _rdsomedev + for _rdsomedev in $(cmdline); do + printf "%s\n" "$_rdsomedev" >> "${initdir:?}/etc/cmdline.d/94zdev.conf" + done + fi + _tempfile=$(mktemp --tmpdir dracut-zdev.XXXXXX) # work with systems that are not based on chzdev persistent config diff --git a/zdev/dracut/95zdev/module-setup.sh b/zdev/dracut/95zdev/module-setup.sh index 30c12760..925d2b47 100644 --- a/zdev/dracut/95zdev/module-setup.sh +++ b/zdev/dracut/95zdev/module-setup.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright IBM Corp. 2016, 2017 +# Copyright IBM Corp. 2016, 2023 # # s390-tools is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. @@ -10,7 +10,7 @@ # This module installs configuration files (udev rules and modprobe.conf # files) required to enable the root device on s390. It will only work when # the root device was configured using the chzdev tool. In addition, -# a hook is installed to parse rd.zdev= kernel parameters. +# hooks are installed to parse rd.zdev= and rd.zfcp= kernel parameters. # # called by dracut @@ -31,6 +31,7 @@ check() { # Ensure that required tools are available require_binaries chzdev lszdev /lib/s390-tools/zdev_id || return 1 require_binaries sed || return 1 + require_binaries grep sort uniq || return 1 return 0 } @@ -40,6 +41,20 @@ depends() { return 0 } +# called by dracut and (conditionally) locally by install() +# Generate rd.zfcp dracut cmdline options for each zfcp-attached +# SCSI disk in dracut's device dependency graph (to mount the root-fs, +# or to access the kdump target). With "dracut --print-cmdline", dracut +# prints the list. With "dracut --hostonly-cmdline" [the case where +# install() calls cmdline()], dracut stores the list inside the generated +# initrd. +cmdline() { + # shellcheck disable=SC2154 + if [[ $hostonly ]]; then + for_each_host_dev_and_slaves_all zdev_check_dev | sort | uniq + fi +} + # called by dracut installkernel() { # Add modules for all device types supported by chzdev (required for @@ -55,15 +70,26 @@ install() { # Ensure that required tools are available inst_multiple chzdev lszdev vmcp /lib/s390-tools/zdev_id + inst_multiple grep # Hook to parse zdev kernel parameter inst_hook cmdline 95 "$moddir/parse-zdev.sh" + # Hook to parse zfcp dracut cmdline parameter + inst_hook cmdline 95 "$moddir/parse-zfcp.sh" # Rule to automatically enable devices when running in DPM inst_rules "81-dpm.rules" # Obtain early + root device configuration + # shellcheck disable=SC2154 + if [[ $hostonly_cmdline == "yes" ]]; then + local _rdsomedev + for _rdsomedev in $(cmdline); do + printf "%s\n" "$_rdsomedev" >> "${initdir:?}/etc/cmdline.d/94zdev.conf" + done + fi + # If enabled, add the host-specific config of required devices into initrd # shellcheck disable=SC2154 [[ $hostonly ]] || return 0 diff --git a/zdev/dracut/95zdev/parse-zfcp.sh b/zdev/dracut/95zdev/parse-zfcp.sh new file mode 100644 index 00000000..b6c02b47 --- /dev/null +++ b/zdev/dracut/95zdev/parse-zfcp.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright IBM Corp. 2023 +# +# s390-tools is free software; you can redistribute it and/or modify +# it under the terms of the MIT license. See LICENSE for details. +# +# 95zdev/parse-zfcp.sh +# Parse the command line for rd.zfcp parameters. These +# parameters are evaluated and used to configure zfcp devices. +# + +zdev_zfcp_base_args="--no-settle --yes --quiet --no-root-update --force" + +for zdev_zfcp_arg in $(getargs rd.zfcp -d 'rd_ZFCP='); do + ( + IFS_SAVED="$IFS" + IFS="," # did not work in front of built-in set command below + # shellcheck disable=SC2086 + set -- $zdev_zfcp_arg + IFS=":" args="$*" + IFS="$IFS_SAVED" + if [ "$#" -eq 1 ]; then + # shellcheck disable=SC2086 + chzdev --enable --persistent $zdev_zfcp_base_args \ + zfcp-host "$args" + else + # shellcheck disable=SC2086 + chzdev --enable --persistent $zdev_zfcp_base_args \ + zfcp-lun "$args" + fi + ) +done +unset zdev_zfcp_arg +unset zdev_zfcp_base_args diff --git a/zdev/dracut/95zdev/zdev-lib.sh b/zdev/dracut/95zdev/zdev-lib.sh index a7f729f0..6643b9f8 100644 --- a/zdev/dracut/95zdev/zdev-lib.sh +++ b/zdev/dracut/95zdev/zdev-lib.sh @@ -25,3 +25,78 @@ zdev_is_kdump() { fi return 1 } + +zdev_zfcp_auto_lun_scan_active() { + local _fcpdevsysfs=$1 + local _porttype _lunscan + read -r _porttype < "$_fcpdevsysfs"/host*/fc_host/host*/port_type + read -r _lunscan < /sys/module/zfcp/parameters/allow_lun_scan + if [[ "$_porttype" == "NPIV VPORT" && "$_lunscan" == "Y" ]]; then + return 0 + fi + return 1 +} + +# zdev_check_dev() can be extended for other device types such as DASD or PCIe +zdev_check_dev() { + local _dev=$1 + local _devsysfs _devtype _subsystem _driver + local _intlun _fcplun _scsitarget _wwpn _hbaid + _devsysfs=$( + cd -P /sys/dev/block/"$_dev" 2> /dev/null && echo "$PWD" + ) + # This is roughly what systemd's udev-builtin-path_id does for zfcp: + while [[ -n "$_devsysfs" ]]; do + # ascend to parent: strip last path part + _devsysfs=${_devsysfs%/*} + _subsystem=$( + cd -P "$_devsysfs"/subsystem 2> /dev/null && echo "$PWD" + ) + if [[ "${_subsystem##*/}" == "scsi" ]]; then + _devtype=$(grep "^DEVTYPE=" "$_devsysfs"/uevent) + # check for FCP LUN + if [[ "$_devtype" == "DEVTYPE=scsi_device" ]]; then + _intlun=${_devsysfs##*:} + # convert _intlun to _fcplun [int_to_scsilun()] + _fcplun=0 + ((_fcplun |= (_intlun & 0x000000000000ffff) << 48)) + ((_fcplun |= (_intlun & 0x00000000ffff0000) << 16)) + ((_fcplun |= (_intlun & 0x0000ffff00000000) >> 16)) + ((_fcplun |= (_intlun & 0xffff000000000000) >> 48)) + printf -v _fcplun "0x%016x" "$_fcplun" + # bail out if not scsi_transport_fc + [[ "${_devsysfs/*rport-*/FOUND}" == "FOUND" ]] || return 0 + continue + fi + # check for target WWPN + if [[ "$_devtype" == "DEVTYPE=scsi_target" ]]; then + _scsitarget=${_devsysfs##*/} + read -r _wwpn < "$_devsysfs/fc_transport/$_scsitarget/port_name" + continue + fi + fi + if [[ "${_subsystem##*/}" == "ccw" ]]; then + _driver=$( + cd -P "$_devsysfs"/driver 2> /dev/null && echo "$PWD" + ) + # check for FCP device (vHBA) bus-ID + if [[ "${_driver##*/}" == "zfcp" ]]; then + _hbaid=${_devsysfs##*/} + # drop full path and use zfcp auto LUN scan, if: + # - not building for kdump which has zfcp auto LUN scan off + # - and zfcp auto LUN scan is available + if ! zdev_is_kdump && \ + zdev_zfcp_auto_lun_scan_active "$_devsysfs"; then + unset _wwpn + unset _fcplun + fi + if [[ -n "$_wwpn" ]] && [[ -n "$_fcplun" ]]; then + printf " rd.zfcp=%s,%s,%s\n" "$_hbaid" "$_wwpn" "$_fcplun" + else + printf " rd.zfcp=%s\n" "$_hbaid" + fi + break + fi + fi + done +} diff --git a/zdev/dracut/Makefile b/zdev/dracut/Makefile index f7911f71..5da887a1 100644 --- a/zdev/dracut/Makefile +++ b/zdev/dracut/Makefile @@ -21,6 +21,7 @@ install: $(INSTALL) -m 755 $(ZDEVDIR)/module-setup.sh \ $(ZDEVDIR)/parse-zdev.sh \ $(ZDEVDIR)/zdev-lib.sh \ + $(ZDEVDIR)/parse-zfcp.sh \ $(DESTDIR)$(DRACUTMODDIR)/$(ZDEVDIR)/ $(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/$(ZDEVKDUMPDIR) $(INSTALL) -m 755 $(ZDEVKDUMPDIR)/module-setup.sh \