Skip to content

Commit

Permalink
zdev/dracut: add rd.zfcp cmdline option handling
Browse files Browse the repository at this point in the history
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

Signed-off-by: Steffen Maier <[email protected]>
  • Loading branch information
steffen-maier committed Nov 28, 2023
1 parent e392ec7 commit 97aa088
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 3 deletions.
31 changes: 30 additions & 1 deletion zdev/dracut/95zdev-kdump/module-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
Expand All @@ -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
Expand All @@ -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
Expand Down
30 changes: 28 additions & 2 deletions zdev/dracut/95zdev/module-setup.sh
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
Expand All @@ -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
}
Expand All @@ -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
Expand All @@ -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
Expand Down
35 changes: 35 additions & 0 deletions zdev/dracut/95zdev/parse-zfcp.sh
Original file line number Diff line number Diff line change
@@ -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
75 changes: 75 additions & 0 deletions zdev/dracut/95zdev/zdev-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
1 change: 1 addition & 0 deletions zdev/dracut/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down

0 comments on commit 97aa088

Please sign in to comment.