# SPDX-License-Identifier: MIT
#
# chreipl-fcp-mpath: use multipath information to change FCP IPL target
# (C) Copyright IBM Corp. 2021

# Did the event affect a multipath or scsi disk device?
ACTION=="change", KERNEL=="dm-[0-9]*", SUBSYSTEM=="block",		\
	ENV{DM_UUID}=="mpath-*", ENV{DM_ACTION}=="PATH_FAILED",		\
	GOTO="chreipl_fcp_mpath_path_change"
ACTION=="change", KERNEL=="dm-[0-9]*", SUBSYSTEM=="block",		\
	ENV{DM_UUID}=="mpath-*", ENV{DM_ACTION}=="PATH_REINSTATED",	\
	GOTO="chreipl_fcp_mpath_path_change"
ACTION=="add", KERNEL=="sd[a-z]*", SUBSYSTEM=="block",			\
	GOTO="chreipl_fcp_mpath_path_change"
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"

# Consider the following scenarios.
# Either:
#
# (A) We recognized a new SCSI Disk. This might represent:
#     (a) the path we want to ReIPL from;
#     (b) an alternative path to the volume we want to ReIPL from;
#     (c) a path to some unrelated volume.
#
# Or:
#
# (B) We recognized a PATH_ event for a multipath device. This might represent:
#     the path we want to ReIPL from:
#         (a) went away;
#         (b) came back online;
#     an alternative path to the volume we want to ReIPL from:
#         (c) went away;
#         (d) came back online;
#     (e) some unrelated multipath device saw an event.

# Test whether the affected device is, or contains, the current IPL target.
#
# This covers scenarios:
#     (A) (a),
#     (B) (a)/(b)/(c)/(d)
PROGRAM!="chreipl-fcp-mpath-is-ipl-tgt",				\
	ENV{CHREIPL_FCP_MPATH_IS_TGT}="false",				\
	GOTO="chreipl_fcp_mpath_not_direct_match"
ENV{CHREIPL_FCP_MPATH_IS_TGT}="true"

# Record the WWID, Device-Bus-ID, Remote WWPN, and LUN of the ReIPL target
# (see `chreipl-fcp-mpath-is-ipl-vol` for usecases). This information
# might change, depending on whether the machine operator changes the ReIPL
# target to a different volume.
#
# XXX: Because the kernel doesn't generate any events upon changing of
#      the ReIPL target, the chreipl-fcp-mpath toolset can't take any
#      actions until the next path event for the new target is
#      generated. Following that, we assume that when the machine
#      operator changes the ReIPL target, the new target is reachable
#      and in a good state at this point in time.
PROGRAM!="chreipl-fcp-mpath-record-volume-identifier",			\
	GOTO="chreipl_fcp_mpath_try_change_ipl_path"
GOTO="chreipl_fcp_mpath_try_change_ipl_path"

# If the even subject is not a direct match (not the sdev that is the current
# ReIPL target, and not a mpath device that contains the current ReIPL target)
LABEL="chreipl_fcp_mpath_not_direct_match"

# While this sdev/mpath device doesn't directly correspond to the path
# currently set as ReIPL target, it might still point to the same volume.
#
# For mpath devices this can happen if the original ReIPL target is completely
# gone from the machine, and so there is no way we can successfully, directly
# compare the ReIPL parameters to the sdevs of the mpath device.
#
# For cases like these we recorded the volume identifier, which we now can
# compare, and so still decide whether we are addressing the correct volume.
#
# This covers scenarios:
#     (A) (b)/(c),
#     (B) (c)/(d)/(e)
#
# XXX: we recorded WWID, Device-Bus-ID, Remote WWPN, LUN of the ReIPL target at
#      the time; if the latter three don't match the current ReIPL setting
#      anymore, we have to assume that someone changed the ReIPL target
#      manually, and we cannot use the WWID anymore since we can't possibly
#      know whether that stayed the same when the change was done.
PROGRAM!="chreipl-fcp-mpath-is-ipl-vol", GOTO="chreipl_fcp_mpath_end"

# We are here because of scenarios:
#     (A) (a)/(b),
#     (B) (a)/(b)/(c)/(d)
LABEL="chreipl_fcp_mpath_try_change_ipl_path"
RUN{program}+="chreipl-fcp-mpath-try-change-ipl-path"

LABEL="chreipl_fcp_mpath_end"
