From 2dbaf9f9919a602fede9482c4ab568c23fac5ef2 Mon Sep 17 00:00:00 2001 From: Benjamin Block Date: Fri, 17 Sep 2021 12:29:47 +0200 Subject: [PATCH] chreipl-fcp-mpath: test if the system uses s390x IPL and re-IPL is from FCP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add second filter stage to the udev rules: only continue with the toolset, if the system uses s390x IPL and if the current re-IPL target is from FCP. For the test, whether the next re-IPL target is planned to be done from FCP, a helper `chreipl-fcp-mpath-is-reipl-zfcp` is added, and the information in /sys/firmware/reipl/reipl_type is used. If either one or both of the tests are not true, the udev rules will exit. For debugging, the toolset can be built with the Make variable `D` set to 1 (e.g.: make D=1; make install D=1). This causes the toolset to write shell traces of the helper to $(DEBUGOUTDIR) (per default: /run/udev); otherwise no output is generated. `dbginfo.sh` will be changed to collect this data automatically. Reviewed-by: Steffen Maier Signed-off-by: Benjamin Block Signed-off-by: Jan Höppner --- chreipl-fcp-mpath/.gitignore | 3 + chreipl-fcp-mpath/Makefile | 99 ++++++++++++++++++- .../chreipl-fcp-mpath-common.sh.in | 44 +++++++++ .../chreipl-fcp-mpath-is-reipl-zfcp.in | 25 +++++ chreipl-fcp-mpath/chreipl-fcp-mpath.mak | 25 +++++ .../udev/rules.d/70-chreipl-fcp-mpath.rules | 8 ++ 6 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 chreipl-fcp-mpath/.gitignore create mode 100644 chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh.in create mode 100644 chreipl-fcp-mpath/chreipl-fcp-mpath-is-reipl-zfcp.in diff --git a/chreipl-fcp-mpath/.gitignore b/chreipl-fcp-mpath/.gitignore new file mode 100644 index 00000000..e1121d76 --- /dev/null +++ b/chreipl-fcp-mpath/.gitignore @@ -0,0 +1,3 @@ +# build artifacts +/chreipl-fcp-mpath-common.sh +/chreipl-fcp-mpath-is-reipl-zfcp diff --git a/chreipl-fcp-mpath/Makefile b/chreipl-fcp-mpath/Makefile index 0294ecba..4ea3423f 100644 --- a/chreipl-fcp-mpath/Makefile +++ b/chreipl-fcp-mpath/Makefile @@ -40,9 +40,27 @@ chreipl-fcp-mpath-clean: all: chreipl-fcp-mpath clean: chreipl-fcp-mpath-clean -udev/rules.d/70-chreipl-fcp-mpath.rules: +# common function used in the helper scripts +CHREIPL_FCP_MPATH_COMMON := \ + chreipl-fcp-mpath-common.sh +CHREIPL_FCP_MPATH_UDEV_HELPER := \ + chreipl-fcp-mpath-is-reipl-zfcp + +$(CHREIPL_FCP_MPATH_UDEV_HELPER) $(CHREIPL_FCP_MPATH_COMMON): $(MAKEFILE_LIST) +$(CHREIPL_FCP_MPATH_UDEV_HELPER) $(CHREIPL_FCP_MPATH_COMMON): % : %.in + $(call chreiplzfcpmp-sed-buildvar-replace,$(<),$(@)) + chmod a+x $(@) + +$(CHREIPL_FCP_MPATH_UDEV_HELPER): $(CHREIPL_FCP_MPATH_COMMON) + +.PHONY: chreipl-fcp-mpath-udev-helper-clean +chreipl-fcp-mpath-udev-helper-clean: + rm -f $(CHREIPL_FCP_MPATH_UDEV_HELPER) $(CHREIPL_FCP_MPATH_COMMON) + +udev/rules.d/70-chreipl-fcp-mpath.rules: $(CHREIPL_FCP_MPATH_UDEV_HELPER) chreipl-fcp-mpath: udev/rules.d/70-chreipl-fcp-mpath.rules +chreipl-fcp-mpath-clean: chreipl-fcp-mpath-udev-helper-clean # ## Install @@ -69,3 +87,82 @@ chreipl-fcp-mpath-install-udev-rules: udev/rules.d/70-chreipl-fcp-mpath.rules udev/rules.d/70-chreipl-fcp-mpath.rules chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-rules + +# install udev helper programs +INSTDIRS += $(UDEVDIR) + +.PHONY: chreipl-fcp-mpath-install-udev-helper +chreipl-fcp-mpath-install-udev-helper: | $(DESTDIR)$(UDEVDIR) +chreipl-fcp-mpath-install-udev-helper: $(CHREIPL_FCP_MPATH_UDEV_HELPER) + $(INSTALL_EXEC) -t $(DESTDIR)$(UDEVDIR) $(CHREIPL_FCP_MPATH_UDEV_HELPER) + +chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-udev-helper + +# install common library files +INSTDIRS += $(CHREIPLZFCPMPDIR) + +.PHONY: chreipl-fcp-mpath-install-libfiles +chreipl-fcp-mpath-install-libfiles: | $(DESTDIR)$(CHREIPLZFCPMPDIR) +chreipl-fcp-mpath-install-libfiles: $(CHREIPL_FCP_MPATH_COMMON) + $(INSTALL_DATA) -t $(DESTDIR)$(CHREIPLZFCPMPDIR) \ + $(CHREIPL_FCP_MPATH_COMMON) + +chreipl-fcp-mpath-install: chreipl-fcp-mpath-install-libfiles + +# +## Utility +# + +# Utilities for the debug feature of chreipl-fcp-mpath-common.sh. +# +# When `chreipl-fcp-mpath` is built with D=1 (default is D=0), each run +# of one of the helper scripts will create a debug log in $(DEBUGOUTDIR) +# (default: /run/udev) which among other things contains the complete shell +# trace of that script run, with some added information that would not be +# inspectable otherwise with just the trace. +# +# There is currently no way of enabling/disabling this at runtime. +# +# chreipl-fcp-mpath-common.sh defines debug log file name as +# "chreiplzfcpmp-${debug_trace_tag}-${SEQNUM:-0}.XXXXXXXXXX" where SEQNUM is a +# udev rule environment variable and each X is replaced with some [[:alnum:]] +# by mktemp. For a definition of `debug_trace_tag`, please see the comments +# in the source. +# +# The following targets can be used for some simple access and filtering of the +# logs during development. + +DEBUG_LOG_GLOB = $(DEBUGOUTDIR)/chreiplzfcpmp-[[:digit:]][[:digit:]][[:alpha:]][[:alpha:]][[:alpha:]][[:alpha:]]-+([[:digit:]]).[[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]] + +# display all debug log files on the system +.PHONY: chreipl-fcp-mpath-debug-logs +chreipl-fcp-mpath-debug-logs: + @ls -1d $(DEBUG_LOG_GLOB) + +# display only debug log files of script runs that exited with status 0 (= good) +# +# XXX: `sed -n -e '$p'` is used instead of `tail -n1` to prevent an other +# dependency just for that (both invocations do the same thing). +.PHONY: chreipl-fcp-mpath-debug-logs-filter-good +chreipl-fcp-mpath-debug-logs-filter-good: + @for lg in $(DEBUG_LOG_GLOB); do \ + sed -e '/^+ trap_exit$$/,/^+ trap - EXIT$$/d' "$${lg}" \ + | sed -n -e '$$p' \ + | grep -q -e '^+ exit 0$$' || continue; \ + ls -d "$${lg}"; \ + done + +# display only debug log files of script runs that didn't exit with status 0 +# (= bad) +.PHONY: chreipl-fcp-mpath-debug-logs-filter-bad +chreipl-fcp-mpath-debug-logs-filter-bad: + @for lg in $(DEBUG_LOG_GLOB); do \ + sed -e '/^+ trap_exit$$/,/^+ trap - EXIT$$/d' "$${lg}" \ + | sed -n -e '$$p' \ + | grep -q -e '^+ exit 0$$' && continue; \ + ls -d "$${lg}"; \ + done + +.PHONY: chreipl-fcp-mpath-debug-logs-clean +chreipl-fcp-mpath-debug-logs-clean: + rm -f $(DEBUG_LOG_GLOB) diff --git a/chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh.in b/chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh.in new file mode 100644 index 00000000..dd64cc5c --- /dev/null +++ b/chreipl-fcp-mpath/chreipl-fcp-mpath-common.sh.in @@ -0,0 +1,44 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT +# +# chreipl-fcp-mpath: use multipath information to change FCP IPL target +# (C) Copyright IBM Corp. 2021 +# +# Uses the following system-utilities (and shell-builtins): +# GNU coreutils: +# - mktemp + +# Makes use of udev event environment variables: +# SEQNUM + +# (1) don't overwrite existing files using redirects (e.g.: `>`) +set -o noclobber + +# make sure any state files created are only writeable by the owning user +umask 027 + +# create log if DEBUG is enabled (with Make: D=1) +# +# Each script importing this library and expecting a debug log to be created +# must declare a *trace tag* in a variable `debug_trace_tag`. This is used as +# identifier in the log file name. The format is: +# +# [[:digit:]][[:digit:]][[:alpha:]][[:alpha:]][[:alpha:]][[:alpha:]] +# \ /\ / +# --------\ /-------- -------------------\ /------------------- +# \/ \/ +# relative position of some unique abbreviation for the script +# execution in the name, excluding any common prefix +# udev rules +if '@DEBUG@' && [ -v debug_trace_tag ] && tlg="$( + mktemp -p '@debugoutdir@' \ + "chreiplzfcpmp-${debug_trace_tag}-${SEQNUM:-0}.XXXXXXXXXX" \ + 2>/dev/null)" +then + readonly tlg + exec >|"${tlg}" 2>&1 + set -x + set +else + unset tlg +fi diff --git a/chreipl-fcp-mpath/chreipl-fcp-mpath-is-reipl-zfcp.in b/chreipl-fcp-mpath/chreipl-fcp-mpath-is-reipl-zfcp.in new file mode 100644 index 00000000..7b8fb299 --- /dev/null +++ b/chreipl-fcp-mpath/chreipl-fcp-mpath-is-reipl-zfcp.in @@ -0,0 +1,25 @@ +#!/bin/bash +# SPDX-License-Identifier: MIT +# +# chreipl-fcp-mpath: use multipath information to change FCP IPL target +# (C) Copyright IBM Corp. 2021 +# +# Uses the following system-utilities (and shell-builtins): +# Those necessary for sourced library: +# - chreipl-fcp-mpath-common.sh + +# Find out whether ReIPL is gonna happen from a SCSI volume attached via zFCP + +# shellcheck disable=SC2034 +declare -gr debug_trace_tag=00iriz +# shellcheck disable=SC1091 +source '@chreiplzfcpmp-lib@' || exit 127 + +declare reipl_type + +{ read -r reipl_type _ < /sys/firmware/reipl/reipl_type; } 2>/dev/null || exit 1 +if '@DEBUG@'; then declare -p reipl_type 1>&2; fi + +[ "${reipl_type}" = "fcp" ] || exit 2 + +exit 0 diff --git a/chreipl-fcp-mpath/chreipl-fcp-mpath.mak b/chreipl-fcp-mpath/chreipl-fcp-mpath.mak index ac022d43..642f3713 100644 --- a/chreipl-fcp-mpath/chreipl-fcp-mpath.mak +++ b/chreipl-fcp-mpath/chreipl-fcp-mpath.mak @@ -6,14 +6,39 @@ # Uses the following system-utilities (and shell-builtins): # Utilities list in GNU Make Conventions: # https://www.gnu.org/software/make/manual/make.html#Utilities-in-Makefiles +# GNU coreutils: +# - mktemp # ## Paths and Build Variables # # https://www.gnu.org/software/make/manual/make.html#Directory-Variables +CHREIPLZFCPMPDIR = $(USRLIBDIR)/chreipl-fcp-mpath UDEVDIR = $(USRLIBDIR)/udev UDEVRULESDIR = $(UDEVDIR)/rules.d +UDEVRUNDIR = /run/udev +DEBUGOUTDIR = $(UDEVRUNDIR) INSTALL_EXEC = $(INSTALL) -g $(GROUP) -o $(OWNER) --preserve-timestamps INSTALL_DATA = $(INSTALL_EXEC) --mode=0644 + +.DELETE_ON_ERROR: + +# export build-time definitions to the scripts/built-components +define chreiplzfcpmp-sed-buildvar-replace = +tmpout=$$(mktemp -p ./ .make.tmp.XXXXXXXXXXXXXXXX) && { \ + $(SED) -E \ + -e 's|@DEBUG@|$(if $(filter 1,$(D)),true,false)|g' \ + -e 's|@chreiplzfcpmp-lib@|$(CHREIPLZFCPMPDIR)/chreipl-fcp-mpath-common.sh|g' \ + -e 's|@debugoutdir@|$(DEBUGOUTDIR)|g' \ + $(1) > $${tmpout} \ + && mv $${tmpout} $(2) \ + || { rm $${tmpout}; false; } \ +; } +endef + +.PHONY: clean-mk-temp +clean: clean-mk-temp +clean-mk-temp: + rm -f .make.tmp.[[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]] diff --git a/chreipl-fcp-mpath/udev/rules.d/70-chreipl-fcp-mpath.rules b/chreipl-fcp-mpath/udev/rules.d/70-chreipl-fcp-mpath.rules index f8e490e7..dbf78561 100644 --- a/chreipl-fcp-mpath/udev/rules.d/70-chreipl-fcp-mpath.rules +++ b/chreipl-fcp-mpath/udev/rules.d/70-chreipl-fcp-mpath.rules @@ -15,4 +15,12 @@ ACTION=="add", KERNEL=="sd[a-z]*", SUBSYSTEM=="block", \ GOTO="chreipl_fcp_mpath_end" LABEL="chreipl_fcp_mpath_path_change" +# Is this system IPL'ed (IOW, are we on s390x)? And do we ReIPL via zFCP? +# +# udev(7): If no absolute path is given, the program is expected to live +# in /usr/lib/udev; otherwise, the absolute path must be +# specified. +TEST!="/sys/firmware/ipl", GOTO="chreipl_fcp_mpath_end" +PROGRAM!="chreipl-fcp-mpath-is-reipl-zfcp", GOTO="chreipl_fcp_mpath_end" + LABEL="chreipl_fcp_mpath_end"