* Upgrade s390-tools to version 2.35 (jsc#PED-9591, jsc#PED-10303)

* Changes of existing tools:
  - cpacfstats: Add support for FULL XTS (MSA 10) and HMAC (MSA 11) PAI counter
  - cpuplugd: Make cpuplugd compatible with hiperdispatch
  - dbginfo.sh: Add network sockstat info
  - pvapconfig: s390x exclusive build
  - zdev: Add option to select IPL device
  - zdump/dfo_s390: Support s390 DFO for vr-kernel dumps
  - zipl: Add support of mirror devices
* Bug Fixes:
  - (genprotimg|zipl)/boot: discard .note.package ELF section to save memory
  - netboot/mk-s390image: Fix size when argument is a symlink
  - ziorep_config: Fix warning message when multipath device is not there.
  - zipl: Fix problems when target parameters are specified by user
  - zipl: Fix segfault when creating device-based dumps with '--dry-run'
* Removed obsolete patches
  - s390-tools-2.34-Fix-Rust-compilation-errors.patch
  - s390-tools-01-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
  - s390-tools-02-zipl-src-add-basic-support-for-multiple-target-base-disks.patch
* Revendored vendor.tar.gz

OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=226
This commit is contained in:
Nikolay Gueorguiev 2024-10-08 10:45:41 +00:00 committed by Git OBS Bridge
commit 5f5c63d1e2
97 changed files with 16366 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.osc

13
59-graf.rules.opensuse Normal file
View File

@ -0,0 +1,13 @@
#
# Rules for unique 3270 device nodes created in /dev/3270/
# This file should be installed in /usr/lib/udev/rules.d
#
SUBSYSTEM!="ccw", GOTO="graf_end"
DRIVER!="3270", GOTO="graf_end"
# Configure 3270 device
ACTION=="add", SUBSYSTEM=="ccw", PROGRAM="/usr/sbin/chccwdev -e $kernel"
ACTION=="remove", SUBSYSTEM=="ccw", PROGRAM="/usr/sbin/chccwdev -d $kernel"
LABEL="graf_end"

13
59-graf.rules.suse Normal file
View File

@ -0,0 +1,13 @@
#
# Rules for unique 3270 device nodes created in /dev/3270/
# This file should be installed in /usr/lib/udev/rules.d
#
SUBSYSTEM!="ccw", GOTO="graf_end"
DRIVER!="3270", GOTO="graf_end"
# Configure 3270 device
ACTION=="add", SUBSYSTEM=="ccw", PROGRAM="/sbin/chccwdev -e $kernel"
ACTION=="remove", SUBSYSTEM=="ccw", PROGRAM="/sbin/chccwdev -d $kernel"
LABEL="graf_end"

5
59-prng.rules Normal file
View File

@ -0,0 +1,5 @@
#
# Rule for prandom character device node permissions
# This file should be installed in /usr/lib/udev/rules.d
#
ACTION=="add", SUBSYSTEM=="misc", KERNEL=="prandom", MODE="0444"

23
59-zfcp-compat.rules Normal file
View File

@ -0,0 +1,23 @@
# Rules for creating the ID_PATH for SCSI devices based on the CCW bus
# using the form: ccw-<BUS_ID>-zfcp-<WWPN>:<LUN>
#
ACTION=="remove", GOTO="zfcp_scsi_device_end"
#
# Set environment variable "ID_ZFCP_BUS" to "1" if the devices
# (both disk and partition) are SCSI devices based on FCP devices
#
KERNEL=="sd*", SUBSYSTEMS=="ccw", DRIVERS=="zfcp", ENV{.ID_ZFCP_BUS}="1"
# For SCSI disks
KERNEL=="sd*[!0-9]", SUBSYSTEMS=="scsi", \
ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="disk", \
SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}"
# For partitions on a SCSI disk
KERNEL=="sd*[0-9]", SUBSYSTEMS=="scsi", \
ENV{.ID_ZFCP_BUS}=="1", ENV{DEVTYPE}=="partition", \
SYMLINK+="disk/by-path/ccw-$attr{hba_id}-zfcp-$attr{wwpn}:$attr{fcp_lun}-part%n"
LABEL="zfcp_scsi_device_end"

25
90-s390-tools.conf Normal file
View File

@ -0,0 +1,25 @@
#
# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
# All rights reserved.
#
# Please don't edit this file. Place your settings into
# /etc/modprobe.d/99-local.conf instead.
#
# The dasd_diag_mod kernel module will not function properly
# unless the dasd_fba_mod module is also loaded. However,
# there are no cross-module symbol dependencies that would
# cause and entry to be placed in
# /lib/modules/$(uname -r)/modules.dep
# So, we're adding this "soft" dependency here to make sure that
# any time dasd_diag_mod gets loaded, so will dasd_fba_mod.
#
# Additionally, DASD devices that are supposed to be used in
# DIAG250 mode will have problems because as far as the kernel
# is concerned, and hence udev, the driver is dasd_fba_mod. So,
# we need to also have the reverse dependency so that when
# dasd_fba_mod gets loaded, so will dasd_diag_mod. This will
# prevent problems that would show up in the system log as:
# Setting the DASD online failed because of missing DIAG discipline
#
softdep dasd_diag_mod pre: dasd_fba_mod
softdep dasd_fba_mod pre: dasd_diag_mod

57
README.SUSE.opensuse Normal file
View File

@ -0,0 +1,57 @@
ls - Addons by SUSE
The following utility and its man page have been added to make it
easier to determine the machine type on which Linux is running.
* cputype
Usage: cputype
The following utilities and their man pages have been added by SUSE to
ease the activation and deactivation of devices. These scripts are also
used by YaST. Functionality not provided by these scripts cannot be
provided by YaST.
These scripts also create/delete the needed udev rules.
Detailed information on some parameters are in the
"Device Drivers, Features and Commands" for this release.
General parameters
channel numbers are with lower letters
parameters switching things on or off are
1 for on and 0 for off
* ctc_configure
Usage: /usr/sbin/ctc_configure <read channel> <write channel> <online> [<protocol>]
To configure CTC connections
Valid Parameters for the protocal are 0, 1 and 3
For a detailed explanation please look in the Device Driver book
* dasd_configure
Usage: dasd_configure <ccwid> <online> <use_diag>
To set DASDs online/offline
The use_diag makes only sense under z/VM. In an
LPAR just set it to 0
* iucv_configure
Usage: /usr/sbin/iucv_configure <router> <online>
To set an IUCV IP-network online/offline
* qeth_configure
Usage: /usr/sbin/qeth_configure [options] <read chan> <write chan> <control chan> <online>
Set qeth, hipersocket adapter online/offline.
options could be one of the following:
-i Configure IP takeover
-l Configure Layer2 support
-p NAME QETH Portname to use
-n 1/0 QETH port number to use
* zfcp_disk_configure
Usage: /usr/sbin/zfcp_disk_configure <ccwid> <wwpn> <lun> <online>
set a disk online/offline. This require that the repective
Adapter is online. See command below.
* zfcp_host_configure
Usage: /usr/sbin/zfcp_host_configure <ccwid> <online>
Set a zfcp Adapter online/offline

57
README.SUSE.suse Normal file
View File

@ -0,0 +1,57 @@
ls - Addons by SUSE
The following utility and its man page have been added to make it
easier to determine the machine type on which Linux is running.
* cputype
Usage: cputype
The following utilities and their man pages have been added by SUSE to
ease the activation and deactivation of devices. These scripts are also
used by YaST. Functionality not provided by these scripts cannot be
provided by YaST.
These scripts also create/delete the needed udev rules.
Detailed information on some parameters are in the
"Device Drivers, Features and Commands" for this release.
General parameters
channel numbers are with lower letters
parameters switching things on or off are
1 for on and 0 for off
* ctc_configure
Usage: /sbin/ctc_configure <read channel> <write channel> <online> [<protocol>]
To configure CTC connections
Valid Parameters for the protocal are 0, 1 and 3
For a detailed explanation please look in the Device Driver book
* dasd_configure
Usage: dasd_configure <ccwid> <online> <use_diag>
To set DASDs online/offline
The use_diag makes only sense under z/VM. In an
LPAR just set it to 0
* iucv_configure
Usage: /sbin/iucv_configure <router> <online>
To set an IUCV IP-network online/offline
* qeth_configure
Usage: /sbin/qeth_configure [options] <read chan> <write chan> <control chan> <online>
Set qeth, hipersocket adapter online/offline.
options could be one of the following:
-i Configure IP takeover
-l Configure Layer2 support
-p NAME QETH Portname to use
-n 1/0 QETH port number to use
* zfcp_disk_configure
Usage: /sbin/zfcp_disk_configure <ccwid> <wwpn> <lun> <online>
set a disk online/offline. This require that the repective
Adapter is online. See command below.
* zfcp_host_configure
Usage: /sbin/zfcp_host_configure <ccwid> <online>
Set a zfcp Adapter online/offline

8
_service Normal file
View File

@ -0,0 +1,8 @@
<services>
<service name="cargo_vendor" mode="manual">
<param name="srctar">s390-tools-2.29.0.tar.gz</param>
<param name="compression">zst</param>
<param name="update">true</param>
</service>
<service name="cargo_audit" mode="manual" />
</services>

126
appldata Normal file
View File

@ -0,0 +1,126 @@
#!/bin/sh
# Copyright (c) 2003 SUSE LINUX AG Nuernberg, Germany.
#
# Submit feedback to http://www.suse.de/feedback/
# Local settings
LOCKFILE=/var/lock/appldata
CONFIGFILE=/etc/sysconfig/appldata
# Source config file
if [ -f $CONFIGFILE ]; then
. $CONFIGFILE
else
echo "No config file found (should be $CONFIGFILE)."
exit 1
fi
RETVAL=0
start() {
echo "Starting \"Linux - z/VM Monitor Stream\" ..."
echo -n "(interval $APPLDATA_INTERVAL milliseconds) "
echo $APPLDATA_INTERVAL > /proc/sys/appldata/interval
if [ "$APPLDATA_MEM" = "yes" ]; then
if [ ! -e /proc/sys/appldata/mem ]; then
echo -n "(mem) "
modprobe appldata_mem 2>&1
if [ "$?" -ne 0 ] ; then
exit 1
else
echo 1 > /proc/sys/appldata/mem
fi
fi
fi
if [ "$APPLDATA_OS" = "yes" ]; then
if [ ! -e /proc/sys/appldata/os ]; then
echo -n "(os) "
modprobe appldata_os 2>&1
if [ "$?" -ne 0 ]; then
exit 1
else
echo 1 > /proc/sys/appldata/os
fi
fi
fi
if [ "$APPLDATA_NET_SUM" = "yes" ]; then
if [ ! -e /proc/sys/appldata/net_sum ]; then
echo -n "(net_sum) "
modprobe appldata_net_sum 2>&1
if [ "$?" -ne 0 ]; then
exit 1
else
echo 1 > /proc/sys/appldata/net_sum
fi
fi
fi
echo -n "(timer)"
echo 1 > /proc/sys/appldata/timer
touch $LOCKFILE
}
stop() {
echo -n "Stopping \"Linux - z/VM Monitor Stream\" "
echo -n "(timer"
echo 0 > /proc/sys/appldata/timer
if [ -e /proc/sys/appldata/mem ]; then
echo -n ",mem"
echo 0 > /proc/sys/appldata/mem
rmmod appldata_mem
fi
if [ -e /proc/sys/appldata/os ]; then
echo -n ",os"
echo 0 > /proc/sys/appldata/os
rmmod appldata_os
fi
if [ -e /proc/sys/appldata/net_sum ]; then
echo -n ",net_sum"
echo 0 > /proc/sys/appldata/net_sum
rmmod appldata_net_sum
fi
echo -n ")"
rm -f $LOCKFILE
}
status() {
echo "\"Linux - z/VM Monitor Stream\" status..."
echo -n "interval "
cat /proc/sys/appldata/interval
echo -n "timer "
cat /proc/sys/appldata/timer
echo -n "mem "
if [ -e /proc/sys/appldata/mem ]; then
cat /proc/sys/appldata/mem
else
echo 0
fi
echo -n "os "
if [ -e /proc/sys/appldata/os ]; then
cat /proc/sys/appldata/os
else
echo 0
fi
echo -n "net_sum "
if [ -e /proc/sys/appldata/net_sum ]; then
cat /proc/sys/appldata/net_sum
else
echo 0
fi
}
# How are we called?
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
*)
RETVAL=1
esac
exit $RETVAL

17
appldata.service Normal file
View File

@ -0,0 +1,17 @@
[Unit]
Description=Linux - z/VM Monitor Stream
After=network-online.target remote-fs.target
Wants=network-online.target remote-fs.target
ConditionPathExists=/proc/sys/appldata/interval
ConditionPathExists=!/var/lock/appldata
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/systemd/scripts/appldata start
ExecStartPost=/usr/lib/systemd/scripts/appldata status
ExecStop=/usr/lib/systemd/scripts/appldata stop
[Install]
WantedBy=default.target

5
cargo_config Normal file
View File

@ -0,0 +1,5 @@
[source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "vendor/"

13
cio_ignore.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description=Setup devices for cio_ignore
DefaultDependencies=no
Before=local-fs.target
ConditionKernelCommandLine=cio_ignore
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/systemd/scripts/setup_cio_ignore.sh
[Install]
WantedBy=sysinit.target

73
cputype Normal file
View File

@ -0,0 +1,73 @@
#!/bin/sh
#
# cputype
#
# Copyright (c) 2014-2017, 2019, 2023 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Based on the IBM machine model, returns a (hopefully) human understandable
# string that identifies the processor.
#
# Usage:
# cputype
#
# Return values:
# 1 The script was executed on a system that is a non-IBM mainframe
# architecture
# 2 The search for the machine type in /proc/cpuinfo returned a null string
# 3 The parsing of the machine type returned a null string
# 4 The machine type found is (probably) a new one, and the script needs to
# be updated to handle it.
#
architecture=$(/bin/uname -m)
if [ "${architecture}" != "s390x" -a "${architecture}" != "s390" ]; then
echo "This command is only useful on IBM mainframes." >&2
exit 1
fi
args=$(/usr/bin/grep machine /proc/cpuinfo | awk '{print $11}' )
if [ -z "${args}" ]; then
echo "I couldn't find the machine type. Please report a bug with this output:" >&2
/bin/cat /proc/cpuinfo >&2
echo "******************" >&2
/usr/bin/grep machine /proc/cpuinfo >&2
exit 2
fi
machine=${args:0:4}
if [ -z "${machine}" ] ; then
echo "The machine type came out null. Please report a bug with this output:" >&2
/bin/cat /proc/cpuinfo >&2
exit 3
fi
case "${machine}" in
2064) echo "${machine} = z900 IBM eServer zSeries 900" ;;
2066) echo "${machine} = z800 IBM eServer zSeries 800" ;;
2084) echo "${machine} = z990 IBM eServer zSeries 990" ;;
2086) echo "${machine} = z890 IBM eServer zSeries 890" ;;
2094) echo "${machine} = z9-EC IBM System z9 Enterprise Class" ;;
2096) echo "${machine} = z9-BC IBM System z9 Business Class" ;;
2097) echo "${machine} = z10-EC IBM System z10 Enterprise Class" ;;
2098) echo "${machine} = z10-BC IBM System z10 Business Class" ;;
2817) echo "${machine} = z196 IBM zEnterprise 196" ;;
2818) echo "${machine} = z114 IBM zEnterprise 114" ;;
2827) echo "${machine} = z12-EC IBM zEnterprise EC12" ;;
2828) echo "${machine} = z12-BC IBM zEnterprise BC12" ;;
2964) echo "${machine} = z13 IBM z13" ;;
2965) echo "${machine} = z13s IBM z13s (single frame)" ;;
3906) echo "${machine} = z14 IBM z14" ;;
3907) echo "${machine} = z14 ZR1 IBM z14 ZR1" ;;
8561) echo "${machine} = z15 T01 IBM z15 T01" ;;
8562) echo "${machine} = z15 T02 IBM z15 T02" ;;
3931) echo "${machine} = z16 A01 IBM z16 A01" ;;
3932) echo "${machine} = z16 A02 IBM z16 A02" ;;
*) echo "An unknown machine type was reported: ${machine}" >&2
echo "Please file a bug report with this output:" >&2
/bin/cat /proc/cpuinfo >&2
exit 4
;;
esac

50
cputype.1 Normal file
View File

@ -0,0 +1,50 @@
.TH cputype 1 "April 2014" "s390-tools"
.SH NAME
cputype \- Based on the IBM machine model, returns a (hopefully) human understandable string that identifies the processor.
.SH SYNOPSIS
.B cputype
.SH DESCRIPTION
.B cputype
is intended to make it easy to find out the type of the mainframe system in use, by examining /proc/cpuinfo and converting that to the name typically known by people familiar with the IBM mainframe.
.SH PARAMETERS
.IP None
.SH FILES
.I /proc/cpuinfo
.RS
Read to determine the IBM machine model for the running system.
.RE
.SH DIAGNOSTICS
The following messages may be issued on stderr:
.IP
.B This command is only useful on IBM mainframes.
.RS
The command was executed on a system that is running on a non-IBM mainframe architecture.
Return code 1 is set.
.RE
.IP
.B I couldn't find the machine type. Please report a bug with this output:
.RS
The contents of /proc/cpuinfo are printed as well as the output from the grep command used.
Return code 2 is set.
.RE
.IP
.B The machine type came out null. Please report a bug with this output:
.RS
The contents of /proc/cpuinfo are printed. Return code 3 is set.
.RE
.IP
.B An unknown machine type was reported: mmmm
.RS
.B Please file a bug report with this output:
.RE
.RS
This is most likely seen because the command was run on a newer generation processor
and the script has not been updated with the new model number.
The contents of /proc/cpuinfo are printed. Return code 4 is set.
.RE
.SH Author
Mark Post (mpost@suse.com)
.SH Copyright
Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

114
ctc_configure Normal file
View File

@ -0,0 +1,114 @@
#! /bin/sh
#
# ctc_configure
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Configures a CTC device by calling the IBM-provided chzdev command.
# Whereas this script used to validate the parameters provided to it,
# we now rely on chzdev to do that instead. The script is intended only
# as a "translation layer" to provide backward compatability for older
# scripts and tools that invoke it.
#
# Usage:
# ctc_configure <read channel> <write channel> <online> [<protocol>]
#
# read/write channel = x.y.ssss where
# x is always 0 until IBM creates something that
# uses that number
# y is the logical channel subsystem (lcss) number.
# Most often this is 0, but it could be non-zero
# ssss is the four digit subchannel address of the
# device, in hexidecimal, with leading zeros.
# online = 0 to take the device offline
# 1 to bring the device online
# protocol = 0 Compatibility with peers other than OS/390®, or z/OS, for
# example, a z/VM TCP service machine. This is the default.
# 1 Enhanced package checking for Linux peers.
# 3 For compatibility with OS/390 or z/OS peers.
# 4 For MPC connections to VTAM on traditional mainframe
# operating systems.
#
# Return values:
# Return codes are determined by the chzdev command.
#
mesg () {
echo "$@"
}
debug_mesg () {
case "${DEBUG}" in
yes) mesg "$@" ;;
*) ;;
esac
}
usage(){
echo "Usage: ${0} <read channel> <write channel> <online> [<protocol>]"
echo " read/write channel = x.y.ssss where"
echo " x is always 0 until IBM creates something that"
echo " uses that number"
echo " y is the logical channel subsystem (lcss) number."
echo " Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the"
echo " device, in hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
echo " protocol = 0 Compatibility with peers other than OS/390®, or z/OS, for"
echo " example, a z/VM TCP service machine. This is the default."
echo " 1 Enhanced package checking for Linux peers."
echo " 3 For compatibility with OS/390 or z/OS peers."
echo " 4 For MPC connections to VTAM on traditional mainframe"
echo " operating systems."
}
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATE=$(date)
CTC_READ_CHAN=${1}
CTC_WRITE_CHAN=${2}
ON_OFF=${3}
CTC_MODE=${4}
if [ -z "${CTC_READ_CHAN}" ] || [ -z "${CTC_WRITE_CHAN}" ] || [ -z "${ON_OFF}" ]; then
mesg "You didn't specify all the needed parameters."
usage
exit 1
fi
if [ -f /sys/bus/ccw/devices/${CTC_READ_CHAN}/cutype ]; then
read CU_TYPE < /sys/bus/ccw/devices/${CTC_READ_CHAN}/cutype
else mesg "Psuedo file/sys/bus/ccw/devices/${CTC_READ_CHAN}/cutype doesn't exist."
mesg "Check to see if sysfs is mounted."
exit 1
fi
PARM_LIST=""
if [ "${CU_TYPE}" == "3088/01" ] || [ "${CU_TYPE}" == "3088/60" ]; then
DEV_TYPE="lcs"
else DEV_TYPE="ctc"
if [ -z "${CTC_MODE}" ]; then
PARM_LIST="${PARM_LIST} protocol=0"
else PARM_LIST="${PARM_LIST} protocol=${CTC_MODE}"
fi
fi
if [ "${ON_OFF}" == 0 ]; then
debug_mesg "chzdev -d ${DEV_TYPE} --no-root-update ${CTC_READ_CHAN}"
chzdev -d ${DEV_TYPE} --no-root-update ${CTC_READ_CHAN}
elif [ "${ON_OFF}" == 1 ]; then
debug_mesg "chzdev -e ${DEV_TYPE} --no-root-update ${CTC_READ_CHAN} ${PARM_LIST}"
chzdev -e ${DEV_TYPE} --no-root-update ${CTC_READ_CHAN} ${PARM_LIST}
else mesg "You must specify a 0 or a 1 for the online/offline attribute."
usage
exit 1
fi
RC=${?}
if [ ${RC} -ne 0 ]; then
exit ${RC}
fi

155
ctc_configure.8 Normal file
View File

@ -0,0 +1,155 @@
.TH ctc_configure "8" "July 2013" "s390-tools"
.SH NAME
ctc_configure \- Configures or deconfigures a Channel-to-Channel adapter (CTC) or LAN Channel Station adapter (LCS)
.SH SYNOPSIS
.B ctc_configure read_channel write_channel online [protocol]
.SH DESCRIPTION
.B ctc_configure
is intended to make it easy to persistently add and remove IBM CTC and LCS adapters. In addition to bringing the adapter online or offline, it will also create or delete the necessary udev rules for the adapter.
.SH PARAMETERS
.IP read_channel
The device number of the read channel of the adapter. Takes the form x.y.ssss.
.IP write_channel
The device number of the write channel of the adapter.Takes the form x.y.ssss.
.RS
where
.RS
.B x
is always 0 until IBM creates something that uses that number.
.RE
.RS
.B y
is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero.
.RE
.RS
.B ssss
is the four digit subchannel address of the device, in hexidecimal, with leading zeros. If entered in upper/mixed case, this is automatically converted to lower case.
.RE
.RE
.RS
Keep in mind that for a CTC, the read channel needs to be coupled to the write channel of the peer, and vice versa. This does not apply to LCS adapters.
.RE
.RE
.IP online
Either a literal 1 to bring the adapter online or a literal 0 to take it offline
.IP protocol
.RS
0 Compatibility with peers other than OS/390®, or z/OS, for example, a z/VM TCP service machine. This is the default.
.RE
.RS
1 Enhanced package checking for Linux peers.
.RE
.RS
3 For compatibility with OS/390 or z/OS peers.
.RE
.RS
4 For MPC connections to VTAM on traditional mainframe operating systems.
.RE
.RS
Not needed for LCS adapters.
.SH FILES
.I /etc/udev/rules.d/51-ctcm-<ccwid>.rules
.RE
.I /etc/udev/rules.d/51-lcs-<ccwid>.rules
.RS
These files provide the udev rules necessary to activate a specific CTC or LCS.
.RE
.SH ENVIRONMENT
.IP DEBUG
If set to "yes" some minimal debugging information is output during execution.
.SH DIAGNOSTICS
The following messages may be issued on stdout:
.IP
.B /sysfs not present
.RS
The sysfs file system could not be found in /proc/mounts, so there's nothing the script can
do. Return code 1 is set.
.RE
.IP
.B Invalid device status ${ONLINE}
.RS
A value other than 0 or 1 was specified for the third parameter, online. Return code 2 is set.
.RE
.IP
.B Device ${CTC_READ_CHAN} does not exist
.RS
A non-existent <ccwid> was specified for the first parameter. Remember the x.y.ssss format is necessary. Return code 3 is set.
.RE
.IP
.B Device ${CTC_READ_CHAN} does not exist
.RS
A non-existent <ccwid> was specified for the second parameter. Remember the x.y.ssss format is necessary. Return code 4 is set.
.RE
.IP
.B Not a valid CTC device (cu ${_cutype}, dev ${_devtype})
.RS
The device number specified does not correspond to a valid CTC or LCS device type. Return code 5 is st.
.RE
.IP
.B CTC type mismatch (read: ${tmp_chan}, write: ${CCW_CHAN_GROUP})
.RS
The device number specified for the read channel has a different device type than the device number specified for the write channel. Return code 6 is set.
.RE
.IP
.B Could not load module ${CCW_CHAN_GROUP}
.RS
The kernel module for the device type failed to load. Try "dmesg" to see if there is any indication why. Return code 7 is set.
.RE
.IP
.B CCW devices grouped to different devices
.RS
The read and write channels are already grouped, but not within the same interface. Try again with different devices. Return code 8 is set.
.RE
.IP
.B Could not group ${CCW_CHAN_GROUP} devices ${CTC_READ_CHAN}/${CTC_WRITE_CHAN}
.RS
The attempt to group the read and write channels into an interface failed. Try "dmesg" to see if there is any indication why. Return code 9 is set.
.RE
.IP
.B Could not set device ${CCW_CHAN_ID} online
.RS
The attempt to bring the grouped devices online failed. Try "dmesg" to see if there is any indication why. Return code 10 is set.
.RE
.IP
.B Could not set device ${CCW_CHAN_ID} offline
.RS
The attempt to take the grouped devices offline failed. Try "dmesg" to see if there is any indication why. Return code 11 is set.
.RE
If environment variable DEBUG is set to "yes," the following messages may be issued on stdout:
.IP
.B
Configuring CTC/LCS device ${CTC_READ_CHAN}/${CTC_WRITE_CHAN}
.RS
Just a little bit of verbosity, since it just indicates that we got past certain error checks and will now try to do something useful.
.RE
.IP
.B Group is ${_ccw_groupdir}/drivers/${CCW_CHAN_GROUP}/group
.RS
Just a little bit of verbosity.
.RE
.IP
.B Setting device online
.RS
Just a little bit of verbosity.
.RE
.IP
.B Device ${CCW_CHAN_ID} is already online
.RS
An attempt was made to bring the adapter online when it was already online.
.RE
.IP
.B Setting device offline
.RS
Just a little bit of verbosity.
.RE
.IP
.B Device ${CCW_CHAN_ID} is already offline
.RS
An attempt was made to take the adapter offline when it was already offline.
.RE
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

60
dasd_configure.8 Normal file
View File

@ -0,0 +1,60 @@
.TH dasd_configure "8" "February 2013" "s390-tools"
.SH NAME
dasd_configure \- Configures or deconfigures a Direct Access Storage Device (DASD) volume.
.SH SYNOPSIS
.B dasd_configure [-f -t dasd_type ] ccwid online [use_diag]
.SH DESCRIPTION
.B dasd_configure
is intended to make it easy to persistently add and remove DASD volumes. In addition to bringing the volume online or offline, it will also create or delete the necessary udev rules for the volume.
.SH PARAMETERS
.IP -f
Force creation of udev rules, do not check values in /sys.
.IP -t
Must be either dasd-eckd or dasd-fba. Must be provided if -f is used.
.IP ccwid
The device number of the DASD volume. Takes the form x.y.ssss where
.RS
.B x
is always 0 until IBM creates something that uses that number.
.RE
.RS
.B y
is the subchannel set ID (SSID). Most often this is 0, but it could be non-zero.
.RE
.RS
.B ssss
is the four digit device address of the subchannel, in hexidecimal, with leading zeros. If entered in upper/mixed case, this is automatically converted to lower case.
.RE
.IP online
Either a literal 1 to bring the volume online or a literal 0 to take it offline
.RE
.IP use_diag
Either a literal 1 to use the DIAG driver for this device, or a literal 0 to use the "normal" driver.
.RE
.SH FILES
Please see the documentation of
.B chzdev.
.SH ENVIRONMENT
.IP DEBUG
If set to "yes" some minimal debugging information is output during execution.
.SH DIAGNOSTICS
Messages and return codes are determined by the
.B chzdev
command.
Except for:
.IP
.B Device ${CCW_CHAN_ID} is unformatted
.RS
The DASD volume was brought online, but it has not been formatted with dasdfmt. This condition is really only important for YaST to determine if it should prompt the user to decide if they want to format it or not at that point. Return code 8 is set.
.RE
If environment variable DEBUG is set to "yes," it shows the command line of the invoked
.B chzdev.
Additionally, the following messages may be issued on stdout:
.IP
.B DASD ${CCW_CHAN_ID} did not come online.
.RS
The DASD volume did not come online within the waiting time. Could not check if the DASD is formatted (see above). Return code 17 is set.
.RE
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

160
dasd_configure.opensuse Normal file
View File

@ -0,0 +1,160 @@
#! /bin/sh
#
# dasd_configure
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Configures a DASD device by calling the IBM-provided chzdev command.
# Whereas this script used to validate the parameters provided to it,
# we now rely on chzdev to do that instead. The script is intended only
# as a "translation layer" to provide backward compatability for older
# scripts and tools that invoke it.
#
# Usage:
# dasd_configure [-f -t <dasd_type> ] <ccwid> <online> [use_diag]
#
# -f Override safety checks
# -t DASD type. Must be provided if -f is used. Only dasd-eckd and
# dasd-fba are supported - Deprecated
# ccwid = x.y.ssss where
# x is always 0 until IBM creates something that uses that number
# y is the subchannel set ID (SSID). Most often
# this is 0, but it could be non-zero
# ssss is the four digit device address of the subchannel, in
# hexidecimal, with leading zeros.
# online = 0 to take the device offline
# 1 to bring the device online
# use_diag = 0 to _not_ use z/VM DIAG250 I/O, which is the default
# 1 to use z/VM DIAG250 I/O
#
# Return values:
# Return codes are determined by the chzdev command, with one exception: If a
# DASD volume is not formatted, we will issue a return code of 8.
#
mesg () {
echo "$@"
}
debug_mesg () {
case "${DEBUG}" in
yes) mesg "$@" ;;
*) ;;
esac
}
usage(){
echo "Usage: ${0} [-f -t <dasd_type> ] <ccwid> <online> [use_diag]"
echo
echo " -f Override safety checks"
echo " -t DASD type. Must be provided if -f is used. Only dasd-eckd and"
echo " dasd-fba are supported - Deprecated"
echo " ccwid = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the subchannel set ID (SSID). Most often"
echo " this is 0, but it could be non-zero"
echo " ssss is the four digit device address of the subchannel, in"
echo " hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
echo " use_diag = 0 to _not_ use z/VM DIAG250 I/O, which is the default"
echo " 1 to use z/VM DIAG250 I/O"
}
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATE=$(date)
DASD_FORCE=0
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt --options ft: -n "dasd_configure" -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
eval set -- "${ARGS}"
debug_mesg "All the parms passed were ${ARGS}"
while true; do
case "${1}" in
-f) debug_mesg "This used to mean udev rules will always be generated."
debug_mesg "For chzdev, it means safety checks will be overridden."
debug_mesg "Kinda sorta the same thing, really."
PARM_LIST="${PARM_LIST} -f"
DASD_FORCE=1
shift 1
;;
-t) debug_mesg "This used to set the card type to ${2}"
debug_mesg "Now it gets ignored."
shift 2
;;
--) debug_mesg "Found the end of parms indicator: --"
shift 1
break
;;
*) debug_mesg "At the catch-all select entry"
debug_mesg "What was selected was ${1}"
shift 1
;;
esac
done
CCW_CHAN_ID=${1}
ON_OFF=${2}
USE_DIAG=${3}
if [ -z "${CCW_CHAN_ID}" ] || [ -z "${ON_OFF}" ]; then
mesg "You didn't specify all the needed parameters."
usage
exit 1
fi
if [ -n "${USE_DIAG}" ]; then
PARM_LIST="${PARM_LIST} use_diag=${USE_DIAG}"
else PARM_LIST="${PARM_LIST} use_diag=0"
fi
if [ "${ON_OFF}" == 0 ]; then
debug_mesg "chzdev -d dasd --no-root-update ${CCW_CHAN_ID}"
chzdev -d dasd --no-root-update ${CCW_CHAN_ID}
elif [ "${ON_OFF}" == 1 ]; then
debug_mesg "chzdev -e dasd --no-root-update ${CCW_CHAN_ID} ${PARM_LIST}"
chzdev -e dasd --no-root-update ${CCW_CHAN_ID} ${PARM_LIST}
else mesg "You must specify a 0 or a 1 for the online/offline attribute."
usage
exit 1
fi
RC=${?}
if [ ${RC} -ne 0 ]; then
exit ${RC}
elif [ ${ON_OFF} == 1 ]; then
exitcode=0
# Extract the full busid so that we can reference the proper entries in /sys
BUSID=$(/usr/sbin/lszdev dasd ${CCW_CHAN_ID} | /usr/bin/sed -e 1d | /usr/bin/tr -s " " | /usr/bin/cut -f2 -d" " )
# Make sure the DASD volume came online
for ((counter=0; counter<30; counter++)); do
sleep 0.1
read online < /sys/bus/ccw/devices/${BUSID}/online
if [ ${online} -eq 1 ] ; then
break
fi
done
if [ ${online} -ne 1 ]; then
debug_mesg "DASD ${CCW_CHAN_ID} did not come online."
exit 17
fi
# Check to see if the DASD volume is unformatted. If so, let YaST know.
read status < /sys/bus/ccw/devices/${BUSID}/status
if [ "${status}" == "unformatted" ]; then
mesg "DASD ${CCW_CHAN_ID} is unformatted."
exitcode=8
fi
fi
exit ${exitcode}

160
dasd_configure.suse Normal file
View File

@ -0,0 +1,160 @@
#! /bin/sh
#
# dasd_configure
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Configures a DASD device by calling the IBM-provided chzdev command.
# Whereas this script used to validate the parameters provided to it,
# we now rely on chzdev to do that instead. The script is intended only
# as a "translation layer" to provide backward compatability for older
# scripts and tools that invoke it.
#
# Usage:
# dasd_configure [-f -t <dasd_type> ] <ccwid> <online> [use_diag]
#
# -f Override safety checks
# -t DASD type. Must be provided if -f is used. Only dasd-eckd and
# dasd-fba are supported - Deprecated
# ccwid = x.y.ssss where
# x is always 0 until IBM creates something that uses that number
# y is the subchannel set ID (SSID). Most often
# this is 0, but it could be non-zero
# ssss is the four digit device address of the subchannel, in
# hexidecimal, with leading zeros.
# online = 0 to take the device offline
# 1 to bring the device online
# use_diag = 0 to _not_ use z/VM DIAG250 I/O, which is the default
# 1 to use z/VM DIAG250 I/O
#
# Return values:
# Return codes are determined by the chzdev command, with one exception: If a
# DASD volume is not formatted, we will issue a return code of 8.
#
mesg () {
echo "$@"
}
debug_mesg () {
case "${DEBUG}" in
yes) mesg "$@" ;;
*) ;;
esac
}
usage(){
echo "Usage: ${0} [-f -t <dasd_type> ] <ccwid> <online> [use_diag]"
echo
echo " -f Override safety checks"
echo " -t DASD type. Must be provided if -f is used. Only dasd-eckd and"
echo " dasd-fba are supported - Deprecated"
echo " ccwid = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the subchannel set ID (SSID). Most often"
echo " this is 0, but it could be non-zero"
echo " ssss is the four digit device address of the subchannel, in"
echo " hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
echo " use_diag = 0 to _not_ use z/VM DIAG250 I/O, which is the default"
echo " 1 to use z/VM DIAG250 I/O"
}
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATE=$(date)
DASD_FORCE=0
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt --options ft: -n "dasd_configure" -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
eval set -- "${ARGS}"
debug_mesg "All the parms passed were ${ARGS}"
while true; do
case "${1}" in
-f) debug_mesg "This used to mean udev rules will always be generated."
debug_mesg "For chzdev, it means safety checks will be overridden."
debug_mesg "Kinda sorta the same thing, really."
PARM_LIST="${PARM_LIST} -f"
DASD_FORCE=1
shift 1
;;
-t) debug_mesg "This used to set the card type to ${2}"
debug_mesg "Now it gets ignored."
shift 2
;;
--) debug_mesg "Found the end of parms indicator: --"
shift 1
break
;;
*) debug_mesg "At the catch-all select entry"
debug_mesg "What was selected was ${1}"
shift 1
;;
esac
done
CCW_CHAN_ID=${1}
ON_OFF=${2}
USE_DIAG=${3}
if [ -z "${CCW_CHAN_ID}" ] || [ -z "${ON_OFF}" ]; then
mesg "You didn't specify all the needed parameters."
usage
exit 1
fi
if [ -n "${USE_DIAG}" ]; then
PARM_LIST="${PARM_LIST} use_diag=${USE_DIAG}"
else PARM_LIST="${PARM_LIST} use_diag=0"
fi
if [ "${ON_OFF}" == 0 ]; then
debug_mesg "chzdev -d dasd --no-root-update ${CCW_CHAN_ID}"
chzdev -d dasd --no-root-update ${CCW_CHAN_ID}
elif [ "${ON_OFF}" == 1 ]; then
debug_mesg "chzdev -e dasd --no-root-update ${CCW_CHAN_ID} ${PARM_LIST}"
chzdev -e dasd --no-root-update ${CCW_CHAN_ID} ${PARM_LIST}
else mesg "You must specify a 0 or a 1 for the online/offline attribute."
usage
exit 1
fi
RC=${?}
if [ ${RC} -ne 0 ]; then
exit ${RC}
elif [ ${ON_OFF} == 1 ]; then
exitcode=0
# Extract the full busid so that we can reference the proper entries in /sys
BUSID=$(/sbin/lszdev dasd ${CCW_CHAN_ID} | /usr/bin/sed -e 1d | /usr/bin/tr -s " " | /usr/bin/cut -f2 -d" " )
# Make sure the DASD volume came online
for ((counter=0; counter<30; counter++)); do
sleep 0.1
read online < /sys/bus/ccw/devices/${BUSID}/online
if [ ${online} -eq 1 ] ; then
break
fi
done
if [ ${online} -ne 1 ]; then
debug_mesg "DASD ${CCW_CHAN_ID} did not come online."
exit 17
fi
# Check to see if the DASD volume is unformatted. If so, let YaST know.
read status < /sys/bus/ccw/devices/${BUSID}/status
if [ "${status}" == "unformatted" ]; then
mesg "DASD ${CCW_CHAN_ID} is unformatted."
exitcode=8
fi
fi
exit ${exitcode}

156
dasd_reload.opensuse Normal file
View File

@ -0,0 +1,156 @@
#!/bin/sh
#
# dasd_reload
# $Id: dasd_reload,v 1.2 2004/05/26 15:17:09 hare Exp $
#
# Deconfigures all active DASDs, unloads the modules
# and activates the configured DASDs again.
# Needed to establish an identical device mapping
# in the installation system and in the running system.
# All DASD access need to be cancelled prior to running
# this script.
#
# Usage:
# dasd_reload
#
# Return values:
# 1 Cannot read /proc/modules
# 2 Missing module programs
# 3 /sys not mounted
# 4 Failure on deactivate DASDs
#
if [ ! -r /proc/modules ]; then
echo "Cannot read /proc/modules"
exit 1
fi
if [ ! -x /usr/sbin/rmmod -o ! -x /usr/sbin/modprobe ]; then
echo "Missing module programs"
exit 2
fi
if [ ! -d /sys/bus ]; then
echo "sysfs not mounted"
exit 3
fi
let anymd=0
if [ -f /proc/mdstat ]; then
for mddevice in $(grep active /proc/mdstat | cut -f1 -d:); do
mdadm -S /dev/${mddevice}
let anymd=1
done
udevadm settle
fi
#
# Setting HyperPAV alias devices offline
#
dasd_alias=
let EXITRC=0
for dev in /sys/bus/ccw/devices/*; do
if [ -f ${dev}/use_diag ]; then
read _online < ${dev}/online
read _alias < ${dev}/alias
if [ "$_online" -eq 1 -a "$_alias" -eq 1 ]; then
echo "setting DASD HyperPAV alias $(basename ${dev}) offline"
echo "0" > ${dev}/online
read _online < ${dev}/online
dasd_alias="${dasd_alias} $(basename ${dev})"
if [ "$_online" -eq 1 ]; then
echo "failure on setting DASD HyperPAV alias $(basename ${dev}) offline !"
let EXITRC=4
fi
fi
fi
done
#
# Setting "normal" DASD and HyperPAV base devices offline
#
dasd_base=
for dev in /sys/bus/ccw/devices/*; do
if [ -f ${dev}/use_diag ]; then
read _online < ${dev}/online
read _alias < ${dev}/alias
if [ "$_online" -eq 1 -a "$_alias" -eq 0 ]; then
echo "setting DASD $(basename ${dev}) offline"
echo "0" > ${dev}/online
read _online < ${dev}/online
dasd_base="${dasd_base} $(basename ${dev})"
if [ "$_online" -eq 1 ]; then
echo "failure on setting DASD $(basename ${dev}) offline !"
let EXITRC=4
fi
fi
fi
done
udevadm settle
module_list=
module_test_list="dasd_diag_mod dasd_eckd_mod dasd_fba_mod dasd_mod"
for module in ${module_test_list}; do
if grep -q "${module}" /proc/modules; then
module_list="${module} ${module_list}"
: Unloading ${module}
/usr/sbin/rmmod ${module}
fi
done
udevadm settle
sleep 2
if [ -d /etc/udev/rules.d ]; then
cd /etc/udev/rules.d
#
# Re-activating "normal" DASD and HyperPAV base devices
#
# We need to move all the DASD udev rules out from /etc/udev/rules.d
# because if we don't, then when the first DASD volume gets brought
# back online, they are all brought back online, in a non-deterministic
# order, not the numeric order we expect.
#
mv -i 41-dasd-*.rules 51-dasd-*.rules /tmp
cd /tmp
for dasd in ${dasd_base}; do
for file in 41-dasd-*-${dasd}.rules 51-dasd-${dasd}.rules; do
[ -f "${file}" ] || continue
#
# Special handling is needed for old udev rules that start with 51-
# since the chzdev command won't look for that name
#
prefix="$(echo ${file} | cut -f1 -d-)"
if [ "${prefix}" == "51" ]; then
if [ -h /sys/bus/ccw/drivers/dasd-eckd/${dasd} ]; then
mv -i ${file} 41-dasd-eckd-${dasd}.rules
elif [ -h /sys/bus/ccw/drivers/dasd-fba/${dasd} ]; then
mv -i ${file} 41-dasd-fba-${dasd}.rules
else echo "DASD volume ${dasd} is neither an ECKD or FBA device."
let EXITRC=4
fi
fi
echo Activating ${dasd}
mv -i "${file}" /etc/udev/rules.d/
/usr/sbin/chzdev dasd --apply --configured -q --no-root-update ${dasd}
lsdasd
break
done
done
#
# Re-activating HyperPAV alias devices
#
for dasd in ${dasd_alias}; do
for file in 41-dasd-*-${dasd}.rules 51-dasd-${dasd}.rules; do
[ -f "${file}" ] || continue
echo Activating ${dasd}
mv -i "${file}" /etc/udev/rules.d/
/usr/sbin/chzdev dasd --apply --configured -q --no-root-update ${dasd}
break
done
done
fi
exit ${EXITRC}

156
dasd_reload.suse Normal file
View File

@ -0,0 +1,156 @@
#!/bin/sh
#
# dasd_reload
# $Id: dasd_reload,v 1.2 2004/05/26 15:17:09 hare Exp $
#
# Deconfigures all active DASDs, unloads the modules
# and activates the configured DASDs again.
# Needed to establish an identical device mapping
# in the installation system and in the running system.
# All DASD access need to be cancelled prior to running
# this script.
#
# Usage:
# dasd_reload
#
# Return values:
# 1 Cannot read /proc/modules
# 2 Missing module programs
# 3 /sys not mounted
# 4 Failure on deactivate DASDs
#
if [ ! -r /proc/modules ]; then
echo "Cannot read /proc/modules"
exit 1
fi
if [ ! -x /sbin/rmmod -o ! -x /sbin/modprobe ]; then
echo "Missing module programs"
exit 2
fi
if [ ! -d /sys/bus ]; then
echo "sysfs not mounted"
exit 3
fi
let anymd=0
if [ -f /proc/mdstat ]; then
for mddevice in $(grep active /proc/mdstat | cut -f1 -d:); do
mdadm -S /dev/${mddevice}
let anymd=1
done
udevadm settle
fi
#
# Setting HyperPAV alias devices offline
#
dasd_alias=
let EXITRC=0
for dev in /sys/bus/ccw/devices/*; do
if [ -f ${dev}/use_diag ]; then
read _online < ${dev}/online
read _alias < ${dev}/alias
if [ "$_online" -eq 1 -a "$_alias" -eq 1 ]; then
echo "setting DASD HyperPAV alias $(basename ${dev}) offline"
echo "0" > ${dev}/online
read _online < ${dev}/online
dasd_alias="${dasd_alias} $(basename ${dev})"
if [ "$_online" -eq 1 ]; then
echo "failure on setting DASD HyperPAV alias $(basename ${dev}) offline !"
let EXITRC=4
fi
fi
fi
done
#
# Setting "normal" DASD and HyperPAV base devices offline
#
dasd_base=
for dev in /sys/bus/ccw/devices/*; do
if [ -f ${dev}/use_diag ]; then
read _online < ${dev}/online
read _alias < ${dev}/alias
if [ "$_online" -eq 1 -a "$_alias" -eq 0 ]; then
echo "setting DASD $(basename ${dev}) offline"
echo "0" > ${dev}/online
read _online < ${dev}/online
dasd_base="${dasd_base} $(basename ${dev})"
if [ "$_online" -eq 1 ]; then
echo "failure on setting DASD $(basename ${dev}) offline !"
let EXITRC=4
fi
fi
fi
done
udevadm settle
module_list=
module_test_list="dasd_diag_mod dasd_eckd_mod dasd_fba_mod dasd_mod"
for module in ${module_test_list}; do
if grep -q "${module}" /proc/modules; then
module_list="${module} ${module_list}"
: Unloading ${module}
/sbin/rmmod ${module}
fi
done
udevadm settle
sleep 2
if [ -d /etc/udev/rules.d ]; then
cd /etc/udev/rules.d
#
# Re-activating "normal" DASD and HyperPAV base devices
#
# We need to move all the DASD udev rules out from /etc/udev/rules.d
# because if we don't, then when the first DASD volume gets brought
# back online, they are all brought back online, in a non-deterministic
# order, not the numeric order we expect.
#
mv -i 41-dasd-*.rules 51-dasd-*.rules /tmp
cd /tmp
for dasd in ${dasd_base}; do
for file in 41-dasd-*-${dasd}.rules 51-dasd-${dasd}.rules; do
[ -f "${file}" ] || continue
#
# Special handling is needed for old udev rules that start with 51-
# since the chzdev command won't look for that name
#
prefix="$(echo ${file} | cut -f1 -d-)"
if [ "${prefix}" == "51" ]; then
if [ -h /sys/bus/ccw/drivers/dasd-eckd/${dasd} ]; then
mv -i ${file} 41-dasd-eckd-${dasd}.rules
elif [ -h /sys/bus/ccw/drivers/dasd-fba/${dasd} ]; then
mv -i ${file} 41-dasd-fba-${dasd}.rules
else echo "DASD volume ${dasd} is neither an ECKD or FBA device."
let EXITRC=4
fi
fi
echo Activating ${dasd}
mv -i "${file}" /etc/udev/rules.d/
/sbin/chzdev dasd --apply --configured -q --no-root-update ${dasd}
lsdasd
break
done
done
#
# Re-activating HyperPAV alias devices
#
for dasd in ${dasd_alias}; do
for file in 41-dasd-*-${dasd}.rules 51-dasd-${dasd}.rules; do
[ -f "${file}" ] || continue
echo Activating ${dasd}
mv -i "${file}" /etc/udev/rules.d/
/sbin/chzdev dasd --apply --configured -q --no-root-update ${dasd}
break
done
done
fi
exit ${EXITRC}

20
dasdro Normal file
View File

@ -0,0 +1,20 @@
#!/bin/bash
# checks DASD accessibility in VM and sets Linux-side readonly attributes
# accordingly
modprobe -q vmcp
vmcp q v dasd 2>/dev/null >/dev/null || exit 0 # not running in VM
vmcp q v dasd | while read x dev rest
do
dev=`echo $dev|tr A-F a-f`
roattr=/sys/bus/ccw/devices/?.?.$dev/readonly
test -e $roattr || continue
if echo "$rest"|grep -q R/O
then
echo 1 >$roattr
else
echo 0 >$roattr
fi
done

157
detach_disks.sh.opensuse Normal file
View File

@ -0,0 +1,157 @@
#!/bin/sh
DASDFILE=/tmp/dasd.list.$(mcookie)
DETFILE=/tmp/detach.disks.$(mcookie)
KEEPFILE=/tmp/keep.disks.$(mcookie)
NICFILE=/tmp/nic.list.$(mcookie)
FAILFILE=/tmp/error.$(mcookie)
function expand_RANGE(){
local RANGE=${1}
local RANGE_SAVE=${RANGE}
local DEVNO
local BEGIN=0
local END=0
RANGE=$(IFS=":-"; echo ${RANGE} | cut -f1-2 -d" " )
set -- ${RANGE}
let BEGIN=0x$1 2>/dev/null
let END=0x$2 2>/dev/null
if [ ${BEGIN} -eq 0 ] || [ ${END} -eq 0 ]; then
${msg} "An invalid device number range was specified: ${RANGE_SAVE}" >&2
touch ${FAILFILE}
return
fi
for DEVNO in $(eval echo {${BEGIN}..${END}})
do printf "%d\n" ${DEVNO}
done
}
function usage(){
echo "Usage: ${0} [ -F ] [ -q ] [ -h ]"
echo " -F Exit with failure if any invalid parms are detected."
echo " -q Don't generate any output."
echo " -h Display this help message."
}
msg="echo"
let FORCE_FAIL=0
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt -a --options Fhq -n "detach_devices" -- "$@")
if [ $? -ne 0 ]; then
usage
exit 3
fi
eval set -- "${ARGS}"
for ARG; do
case "${ARG}" in
-F) let FORCE_FAIL=1
shift 1
;;
-h) usage;
exit 0
;;
-q) msg="/bin/true"
shift 1
;;
--) shift 1
;;
*) ${msg} "Extraneous input detected: ${1}"
shift 1
;;
esac
done
if [ -r /etc/sysconfig/virtsetup ]; then
. /etc/sysconfig/virtsetup
else ${msg} "No /etc/sysconfig/virtsetup file was found."
exit 1
fi
# First, get a list of all the DASD devices we have for this guest, in decimal.
# (Trying to handle things in hex gets complicated.)
/usr/sbin/vmcp -b1048576 q v dasd | cut -f2 -d" " |\
while read HEXNO
do let DECNO=0x${HEXNO}
echo ${DECNO}
done > ${DASDFILE} 2>/dev/null
# If the system administrator specified certain devices to be detached
# let's put those device numbers in a file, one per line.
touch ${DETFILE}
for ADDR in $(IFS=", " ; echo ${ZVM_DISKS_TO_DETACH})
do if $(echo ${ADDR} | grep -iqE ":|-" 2>/dev/null)
then expand_RANGE ${ADDR} >> ${DETFILE}
else let DEVNO=0
let DEVNO=0x${ADDR} 2>/dev/null
if [ ${DEVNO} -eq 0 ]; then
${msg} "An invalid device number was specified: ${ADDR}" >&2
touch ${FAILFILE}
else printf "%d\n" ${DEVNO}
fi
fi
done > ${DETFILE}
# If the system administrator specified certain devices that should _not_
# be detached, let's put those in another file, one per line.
touch ${KEEPFILE}
for ADDR in $(IFS=", " ; echo ${ZVM_DISKS_TO_NOT_DETACH})
do if $(echo ${ADDR} | grep -iqE ":|-" 2>/dev/null)
then expand_RANGE ${ADDR} >> ${KEEPFILE}
else let DEVNO=0
let DEVNO=0x${ADDR} 2>/dev/null
if [ ${DEVNO} -eq 0 ]; then
${msg} "An invalid device number was specified: ${ADDR}" >&2
touch ${FAILFILE}
else printf "%d\n" ${DEVNO}
fi
fi
done > ${KEEPFILE}
if [ ${FORCE_FAIL} -eq 1 ] && [ -e ${FAILFILE} ]; then
let RETURN_CODE=1
${msg} "Terminating detach_disk because of input errors."
else
# If the system administrator specified that all "unused" disks should be
# detached, compare the disks lsdasd show as activated to the complete
# list of disks we have currently, and add the inactive ones to the
# file containing devices to be detached
if [ "${ZVM_DETACH_ALL_UNUSED}" == "yes" ]; then
lsdasd -s | sed -e 1,2d | cut -f1 -d" " | \
while read ADDR
do let DEVNO=0x${ADDR}
sed -i -e "/^${DEVNO}$/d" ${DASDFILE}
done
cat ${DASDFILE} >> ${DETFILE}
fi
# Now remove any "to be kept" disks from the detach file
while read DEVNO
do sed -i -e "/^${DEVNO}/d" ${DETFILE}
done < ${KEEPFILE}
# Get a list of all the virtual NICs since they require an
# extra keyword to detach. Contrary to what we've done before
# these will be hex values
/usr/sbin/vmcp -b1048576 q nic | grep Adapter | cut -f2 -d" " | cut -f1 -d. > ${NICFILE}
# Now we sort the device numbers and detach them.
sort -un ${DETFILE} | \
while read DEVNO
do HEXNO=$(printf %04X ${DEVNO})
if grep -q ^${HEXNO}$ ${NICFILE} 2>/dev/null ; then
vmcp detach nic ${HEXNO} 2>/dev/null
else vmcp detach ${HEXNO} 2>/dev/null
fi
done
let RETURN_CODE=0
fi
rm -f ${DASDFILE} ${DETFILE} ${KEEPFILE} ${NICFILE} ${FAILFILE}
exit ${RETURN_CODE}

157
detach_disks.sh.suse Normal file
View File

@ -0,0 +1,157 @@
#!/bin/sh
DASDFILE=/tmp/dasd.list.$(mcookie)
DETFILE=/tmp/detach.disks.$(mcookie)
KEEPFILE=/tmp/keep.disks.$(mcookie)
NICFILE=/tmp/nic.list.$(mcookie)
FAILFILE=/tmp/error.$(mcookie)
function expand_RANGE(){
local RANGE=${1}
local RANGE_SAVE=${RANGE}
local DEVNO
local BEGIN=0
local END=0
RANGE=$(IFS=":-"; echo ${RANGE} | cut -f1-2 -d" " )
set -- ${RANGE}
let BEGIN=0x$1 2>/dev/null
let END=0x$2 2>/dev/null
if [ ${BEGIN} -eq 0 ] || [ ${END} -eq 0 ]; then
${msg} "An invalid device number range was specified: ${RANGE_SAVE}" >&2
touch ${FAILFILE}
return
fi
for DEVNO in $(eval echo {${BEGIN}..${END}})
do printf "%d\n" ${DEVNO}
done
}
function usage(){
echo "Usage: ${0} [ -F ] [ -q ] [ -h ]"
echo " -F Exit with failure if any invalid parms are detected."
echo " -q Don't generate any output."
echo " -h Display this help message."
}
msg="echo"
let FORCE_FAIL=0
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt -a --options Fhq -n "detach_devices" -- "$@")
if [ $? -ne 0 ]; then
usage
exit 3
fi
eval set -- "${ARGS}"
for ARG; do
case "${ARG}" in
-F) let FORCE_FAIL=1
shift 1
;;
-h) usage;
exit 0
;;
-q) msg="/bin/true"
shift 1
;;
--) shift 1
;;
*) ${msg} "Extraneous input detected: ${1}"
shift 1
;;
esac
done
if [ -r /etc/sysconfig/virtsetup ]; then
. /etc/sysconfig/virtsetup
else ${msg} "No /etc/sysconfig/virtsetup file was found."
exit 1
fi
# First, get a list of all the DASD devices we have for this guest, in decimal.
# (Trying to handle things in hex gets complicated.)
/sbin/vmcp -b1048576 q v dasd | cut -f2 -d" " |\
while read HEXNO
do let DECNO=0x${HEXNO}
echo ${DECNO}
done > ${DASDFILE} 2>/dev/null
# If the system administrator specified certain devices to be detached
# let's put those device numbers in a file, one per line.
touch ${DETFILE}
for ADDR in $(IFS=", " ; echo ${ZVM_DISKS_TO_DETACH})
do if $(echo ${ADDR} | grep -iqE ":|-" 2>/dev/null)
then expand_RANGE ${ADDR} >> ${DETFILE}
else let DEVNO=0
let DEVNO=0x${ADDR} 2>/dev/null
if [ ${DEVNO} -eq 0 ]; then
${msg} "An invalid device number was specified: ${ADDR}" >&2
touch ${FAILFILE}
else printf "%d\n" ${DEVNO}
fi
fi
done > ${DETFILE}
# If the system administrator specified certain devices that should _not_
# be detached, let's put those in another file, one per line.
touch ${KEEPFILE}
for ADDR in $(IFS=", " ; echo ${ZVM_DISKS_TO_NOT_DETACH})
do if $(echo ${ADDR} | grep -iqE ":|-" 2>/dev/null)
then expand_RANGE ${ADDR} >> ${KEEPFILE}
else let DEVNO=0
let DEVNO=0x${ADDR} 2>/dev/null
if [ ${DEVNO} -eq 0 ]; then
${msg} "An invalid device number was specified: ${ADDR}" >&2
touch ${FAILFILE}
else printf "%d\n" ${DEVNO}
fi
fi
done > ${KEEPFILE}
if [ ${FORCE_FAIL} -eq 1 ] && [ -e ${FAILFILE} ]; then
let RETURN_CODE=1
${msg} "Terminating detach_disk because of input errors."
else
# If the system administrator specified that all "unused" disks should be
# detached, compare the disks lsdasd show as activated to the complete
# list of disks we have currently, and add the inactive ones to the
# file containing devices to be detached
if [ "${ZVM_DETACH_ALL_UNUSED}" == "yes" ]; then
lsdasd -s | sed -e 1,2d | cut -f1 -d" " | \
while read ADDR
do let DEVNO=0x${ADDR}
sed -i -e "/^${DEVNO}$/d" ${DASDFILE}
done
cat ${DASDFILE} >> ${DETFILE}
fi
# Now remove any "to be kept" disks from the detach file
while read DEVNO
do sed -i -e "/^${DEVNO}/d" ${DETFILE}
done < ${KEEPFILE}
# Get a list of all the virtual NICs since they require an
# extra keyword to detach. Contrary to what we've done before
# these will be hex values
/sbin/vmcp -b1048576 q nic | grep Adapter | cut -f2 -d" " | cut -f1 -d. > ${NICFILE}
# Now we sort the device numbers and detach them.
sort -un ${DETFILE} | \
while read DEVNO
do HEXNO=$(printf %04X ${DEVNO})
if grep -q ^${HEXNO}$ ${NICFILE} 2>/dev/null ; then
vmcp detach nic ${HEXNO} 2>/dev/null
else vmcp detach ${HEXNO} 2>/dev/null
fi
done
let RETURN_CODE=0
fi
rm -f ${DASDFILE} ${DETFILE} ${KEEPFILE} ${NICFILE} ${FAILFILE}
exit ${RETURN_CODE}

181
hsnc Normal file
View File

@ -0,0 +1,181 @@
#! /bin/sh
# Copyright (c) 2003 SUSE LINUX AG Nuernberg, Germany.
#
# Please send feedback to http://www.suse.de/feedback/
#
# /etc/init.d/hsnc
#
# and symbolic its link
#
# /usr/sbin/ip_watcher.pl
# /usr/sbin/xcec-bridge
# /usr/sbin/start_hsnc.sh
# /use/sbin/rchsnc
#
# System startup script for the HiperSockets Network Concentrator
#
# /etc/hsnc.conf should contain the following lines:
#
# operating_mode=[unicast|full|no]
# unicast means, only unicast forwarded between the hsint's and osaint's.
# this is the default mode
# full means, unicast, multicast and broadcast are forwarded, if supported
# by the hardware
#
# hsi_int="<interface> [<interface> [...]]"
# described all the HiperSockets interfaces involved in the HSN
#
# osa_int="<interface>"
# describes the OSA interface connecting to other LANs
#
START_HSNC_BIN=/usr/sbin/start_hsnc.sh
IP_WATCHER_BIN=/usr/sbin/ip_watcher.pl
XCEC_BRIDGE_BIN=/usr/sbin/xcec-bridge
HSNC_CONFIG_FILE=/etc/sysconfig/hsnc
HSNC_CLEANUP_FILE=/var/run/hsnc.cleanup
test -x $START_HSNC_BIN || exit 5
test -x $IP_WATCHER_BIN || exit 5
test -x $XCEC_BRIDGE_BIN || exit 5
# Return values acc. to LSB for all commands but status:
# 0 - success
# 1 - generic or unspecified error
# 2 - invalid or excess argument(s)
# 3 - unimplemented feature (e.g. "reload")
# 4 - insufficient privilege
# 5 - program is not installed
# 6 - program is not configured
# 7 - program is not running
#
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signalling is not supported) are
# considered a success.
#call with cleanup or not
read_config_file() {
if [ "$1" == "cleanup" ]; then
file=$HSNC_CLEANUP_FILE
else
file=$HSNC_CONFIG_FILE
fi
if [ -s $file ]; then
source $file
else
echo -ne "\nCannot read $file: empty or nonexistant! "
# Means not configured:
exit 3
fi
}
#call with cleanup or not
set_osa_mode() {
# for full mode, we set up the osa as multicast router. otherwise, no
# special setup is required for the osa.
if [ "$operating_mode" == "full" ]; then
if [ "$1" == "cleanup" ]; then
echo no_router > /sys/class/net/$osa_int/device/route4
else
echo multicast_router > /sys/class/net/$osa_int/device/route4
fi
fi
}
#call with cleanup or not
set_hsi_mode() {
# set all the involved HiperSockets interfaces as primary_connector. For
# special HA setups, some more tweaking is needed, but then a handcarved
# solution should be used anyway.
for i in $hsi_int ; do
if [ "$1" == "cleanup" ]; then
echo no_router > /sys/class/net/$i/device/route4
else
echo primary_connector > /sys/class/net/$i/device/route4
fi
done
}
do_start_hsnc() {
set_osa_mode
set_hsi_mode
if [ "$operating_mode" == "full" ]; then
$IP_WATCHER_BIN --check
else
$IP_WATCHER_BIN --check $osa_int
fi
CODE=$?
if [ $CODE != 0 ]; then
return $CODE
else
cp $HSNC_CONFIG_FILE $HSNC_CLEANUP_FILE
#
# To match the LSB spec, startproc returns 0,
# even if the program it already running.
#
if [ "$operating_mode" == "full" ]; then
startproc $START_HSNC_BIN
else
startproc $START_HSNC_BIN $osa_int
fi
return $?
fi
}
service="HiperSockets Network concentrator"
case "$1" in
start)
if checkproc $START_HSNC_BIN; then
# Starting an already running service is success:
echo -n "(already running)"
else
if read_config_file; then
do_start_hsnc
RETVAL=$?
exit $RETVAL
fi
fi
;;
stop)
echo -n "Shutting down $service "
# kill ip_watcher, start_hsnc, which started it needs cleans up
# then:
killproc -TERM $IP_WATCHER_BIN
if [ -f $HSNC_CLEANUP_FILE ]; then
read_config_file cleanup
# remove all connector settings(not yet implemented):
set_osa_mode cleanup
set_hsi_mode cleanup
# remove the file in /var/run
rm -f $HSNC_CLEANUP_FILE
else
echo -n "- no cleanup file found "
fi
;;
status)
echo -n "Checking $service "
## Check status with checkproc(8), if process is running
## checkproc will return with exit status 0.
# Status has a slightly different for the status command:
# 0 - service running
# 1 - service dead, but /var/run/ pid file exists
# 2 - service dead, but /var/lock/ lock file exists
# 3 - service not running
# NOTE: checkproc returns LSB compliant status values.
checkproc $START_HSNC_BIN
;;
*)
exit 1
;;
esac

16
hsnc.service Normal file
View File

@ -0,0 +1,16 @@
[Unit]
Description=Start the qeth HiperSockets Network Concentrator
After=network-online.target remote-fs.target
Wants=network-online.target remote-fs.target
ConditionPathExists=/sys/devices/qeth
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/systemd/scripts/hsnc start
ExecStartPost=/usr/lib/systemd/scripts/hsnc status
ExecStop=/usr/lib/systemd/scripts/hsnc stop
[Install]
WantedBy=default.target

64
iucv_configure.8 Normal file
View File

@ -0,0 +1,64 @@
.TH iucv_configure "8" "July 2013" "s390-tools"
.SH NAME
iucv_configure \- Configures or deconfigures a z/VM Inter-User Communications Vehicle (IUCV) network adapter
.SH SYNOPSIS
.B iucv_configure peer_userid online
.SH DESCRIPTION
.B iucv_configure
is intended to make it easy to persistently add and remove z/VM point-to-point IUCV network adapters. In addition to bringing the adapter online or offline, it will also create or delete the necessary udev rules for the adapter.
.SH PARAMETERS
.IP peer_userid
The z/VM userid of the virtual machine on the other end of the point-to-point connection.
.IP online
Either a literal 1 to bring the adapter online or a literal 0 to take it offline
.SH FILES
.I /etc/udev/rules.d/51-iucv-<peer_userid>.rules
.RS
This file provide the udev rules necessary to activate a specific IUCV adapter.
.RE
.SH ENVIRONMENT
.IP DEBUG
If set to "yes" some minimal debugging information is output during execution.
.SH DIAGNOSTICS
The following messages may be issued on stdout:
.IP
.B /sysfs not present
.RS
The sysfs file system could not be found in /proc/mounts, so there's nothing the script can
do. Return code 1 is set.
.RE
.IP
.B No IUCV user name given
.RS
You didn't specify the z/VM userid of the virtual machine to which you want to connect. Return code 2 is set.
.RE
.IP
.B Unable to connect to $PEER_USERID
.RS
The attempt to connect to the IUCV peer failed. Try "dmesg" to see if there is any indication why. Return code 3 is set.
.RE
.IP
.B Unable to remove device $netdev
.RS
The attempt to remove the IUCV adapter failed. Try "dmesg" to see if there is any indication why. Return code 4 is set.
.RE
If environment variable DEBUG is set to "yes," the following messages may be issued on stdout:
.IP
.B
Configuring IUCV device ${PEER_USERID}
.RS
Just a little bit of verbosity, since it just indicates that we got past certain error checks and will now try to do something useful.
.RE
.IP
.B Configured device $iucvdev
.RS
The attempt to create the IUCV adapter was successful.
.RE
.IP
.B Removed device $iucvdev
.RS
The attempt to remove the IUCV adapter was successful.
.RE
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

133
iucv_configure.opensuse Normal file
View File

@ -0,0 +1,133 @@
#! /bin/sh
#
# iucv_configure
#
# Configures a z/VM IUCV network adapter
#
# Usage:
# iucv_configure <peer_userid> <online>
#
# peer_userid = z/VM userid of the IUCV peer
# online = 0 to take the device offline
# 1 to bring the device online
#
# Return values:
# 1 sysfs not mounted
# 2 Invalid status for <online>
# 3 Could not create iucv device
# 4 Could not remove iucv device
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
mesg () {
echo "$@"
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
if [ $# -ne 2 ] ; then
echo "Usage: $0 <peer_userid> <online>"
echo " peer_userid = z/VM userid of the IUCV peer"
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
exit 1
fi
# Get the mount point for sysfs
while read MNTPT MNTDIR MNTSYS MNTTYPE; do
if test "$MNTSYS" = "sysfs"; then
SYSFS="$MNTDIR"
break;
fi
done </proc/mounts
if [ -z "$SYSFS" ]; then
mesg "/sysfs not present"
exit 1
fi
PEER_USERID_LOWER=$1
PEER_USERID=$(echo $1 | tr "a-z" "A-Z")
ONLINE=$2
if [ -z "$PEER_USERID" ] ; then
mesg "No IUCV user name given"
exit 2
fi
if [ -z "$ONLINE" ] ; then
ONLINE=1
fi
_iucv_dir=${SYSFS}/bus/iucv/devices
_iucv_drv=${SYSFS}/bus/iucv/drivers/netiucv
if [ ! -d "$_iucv_drv" ] ; then
modprobe -q netiucv
fi
debug_mesg "Configuring IUCV device ${PEER_USERID}"
for _iucv_dev in $_iucv_dir/netiucv?* ; do
[ -d $_iucv_dev ] || continue
read user < $_iucv_dev/user
if [ "$user" = "$PEER_USERID" ] ; then
# Already configured, ok
iucvdev=${_iucv_dev##*/}
break;
fi
done
if [ -z "$iucvdev" -a $ONLINE -eq 1 ] ; then
echo $PEER_USERID > $_iucv_drv/connection
if [ $? -ne 0 ] ; then
mesg "Unable to connect to $PEER_USERID"
exit 3
fi
for _iucv_dev in $_iucv_dir/netiucv?* ; do
[ -d $_iucv_dev ] || continue
read user < $_iucv_dev/user
if [ "$user" = "$PEER_USERID" ] ; then
iucvdev=${_iucv_dev##*/}
break;
fi
done
if [ "$iucvdev" ] ; then
debug_mesg "Configured device $iucvdev"
fi
elif [ "$iucvdev" -a $ONLINE -eq 0 ] ; then
for _net_dev in $_iucv_dir/$iucvdev/net/* ; do
[ -d $_net_dev ] || continue
netdev=${_net_dev##*/}
break;
done
if [ "$netdev" ] ; then
echo $netdev > $_iucv_drv/remove
if [ $? -ne 0 ] ; then
mesg "Unable to remove device $netdev"
exit 4
else
debug_mesg "Removed device $iucvdev"
rm -f /etc/udev/rules.d/51-iucv-$PEER_USERID.rules /etc/udev/rules.d/51-iucv-$PEER_USERID_LOWER.rules
iucvdev=
fi
fi
fi
if [ "$iucvdev" ] ; then
cat > /etc/udev/rules.d/51-iucv-$PEER_USERID.rules <<EOF
ACTION=="add", SUBSYSTEM=="subsystem", KERNEL=="iucv", RUN+="/usr/sbin/modprobe netiucv"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="netiucv", ATTR{connection}="$PEER_USERID"
EOF
fi
exit

133
iucv_configure.suse Normal file
View File

@ -0,0 +1,133 @@
#! /bin/sh
#
# iucv_configure
#
# Configures a z/VM IUCV network adapter
#
# Usage:
# iucv_configure <peer_userid> <online>
#
# peer_userid = z/VM userid of the IUCV peer
# online = 0 to take the device offline
# 1 to bring the device online
#
# Return values:
# 1 sysfs not mounted
# 2 Invalid status for <online>
# 3 Could not create iucv device
# 4 Could not remove iucv device
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
mesg () {
echo "$@"
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
if [ $# -ne 2 ] ; then
echo "Usage: $0 <peer_userid> <online>"
echo " peer_userid = z/VM userid of the IUCV peer"
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
exit 1
fi
# Get the mount point for sysfs
while read MNTPT MNTDIR MNTSYS MNTTYPE; do
if test "$MNTSYS" = "sysfs"; then
SYSFS="$MNTDIR"
break;
fi
done </proc/mounts
if [ -z "$SYSFS" ]; then
mesg "/sysfs not present"
exit 1
fi
PEER_USERID_LOWER=$1
PEER_USERID=$(echo $1 | tr "a-z" "A-Z")
ONLINE=$2
if [ -z "$PEER_USERID" ] ; then
mesg "No IUCV user name given"
exit 2
fi
if [ -z "$ONLINE" ] ; then
ONLINE=1
fi
_iucv_dir=${SYSFS}/bus/iucv/devices
_iucv_drv=${SYSFS}/bus/iucv/drivers/netiucv
if [ ! -d "$_iucv_drv" ] ; then
modprobe -q netiucv
fi
debug_mesg "Configuring IUCV device ${PEER_USERID}"
for _iucv_dev in $_iucv_dir/netiucv?* ; do
[ -d $_iucv_dev ] || continue
read user < $_iucv_dev/user
if [ "$user" = "$PEER_USERID" ] ; then
# Already configured, ok
iucvdev=${_iucv_dev##*/}
break;
fi
done
if [ -z "$iucvdev" -a $ONLINE -eq 1 ] ; then
echo $PEER_USERID > $_iucv_drv/connection
if [ $? -ne 0 ] ; then
mesg "Unable to connect to $PEER_USERID"
exit 3
fi
for _iucv_dev in $_iucv_dir/netiucv?* ; do
[ -d $_iucv_dev ] || continue
read user < $_iucv_dev/user
if [ "$user" = "$PEER_USERID" ] ; then
iucvdev=${_iucv_dev##*/}
break;
fi
done
if [ "$iucvdev" ] ; then
debug_mesg "Configured device $iucvdev"
fi
elif [ "$iucvdev" -a $ONLINE -eq 0 ] ; then
for _net_dev in $_iucv_dir/$iucvdev/net/* ; do
[ -d $_net_dev ] || continue
netdev=${_net_dev##*/}
break;
done
if [ "$netdev" ] ; then
echo $netdev > $_iucv_drv/remove
if [ $? -ne 0 ] ; then
mesg "Unable to remove device $netdev"
exit 4
else
debug_mesg "Removed device $iucvdev"
rm -f /etc/udev/rules.d/51-iucv-$PEER_USERID.rules /etc/udev/rules.d/51-iucv-$PEER_USERID_LOWER.rules
iucvdev=
fi
fi
fi
if [ "$iucvdev" ] ; then
cat > /etc/udev/rules.d/51-iucv-$PEER_USERID.rules <<EOF
ACTION=="add", SUBSYSTEM=="subsystem", KERNEL=="iucv", RUN+="/sbin/modprobe netiucv"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="netiucv", ATTR{connection}="$PEER_USERID"
EOF
fi
exit

217
killcdl.opensuse Normal file
View File

@ -0,0 +1,217 @@
#!/bin/sh
#
# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
# Released under the GNU General Public License version 2.
#
let FORCE=0
DEVPARM=""
usage(){
echo "Usage: ${0} [ -f ] devno|busid"
echo " -f Force unformatting for DASD volumes in the CMS device range of 19x."
echo " devno The \"plain\" device number of the volume, e.g. 3184."
echo " busid The full specification of the volume, e.g., 0.0.3184."
}
ARCH="$(/usr/bin/uname -m)"
if [ "${ARCH}" != "s390x" ] && [ "${ARCH}" != "s390" ]; then
echo "This script is only useful on IBM mainframes."
exit 1
fi
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt -a --options f -n "killcdl" -- "$@")
if [ $? -ne 0 ]; then
usage
exit 3
fi
eval set -- "${ARGS}"
for ARG; do
case "${ARG}" in
-f) FORCE=1
shift 1
;;
--) shift 1
;;
[0-9a-fA-F]*) if [ ! -z "${DEVPARM}" ]; then
echo "More than one parameter specified."
usage
exit 4
fi
DEVPARM=${1}
shift 1
;;
*) echo "That looks invalid"
usage
exit 5
;;
esac
done
if [ -z "${DEVPARM}" ]; then
echo "You must specify the device number of the DASD volume to be unformatted."
usage
exit 6
fi
DEVNO=$(echo "${DEVPARM}" | tr A-Z a-z)
# Validate the device number or busid provided
set -- $(IFS='.'; echo ${DEVNO})
let NUMPARMS=${#}
if [ ${NUMPARMS} -ne 1 ] && [ ${NUMPARMS} -ne 3 ]; then
echo "You have not specified the device number in a recognizable format."
echo "It must either be the plain device number, e.g., 0123, or in"
echo "so-called busid format, e.g., 0.0.0123"
exit 7
fi
# Just a device number, SIMPLE=1. A busid, SIMPLE=0
SIMPLE=0
if [ ${NUMPARMS} -eq 1 ]; then
let SIMPLE=1
let FIRST=0
let FIRSTLEN=1
let SECOND=0
let SECONDLEN=1
DEVNO="${1}"
let DEVNOLEN=${#1}
else FIRST="${1}"
let FIRSTLEN=${#FIRST}
SECOND="${2}"
let SECONDLEN=${#SECOND}
DEVNO="${3}"
let DEVNOLEN=${#3}
fi
if [ ${FIRSTLEN} -ne 1 ] || [ ${SECONDLEN} -ne 1 ]; then
echo "The first and second fields of the busid may only be one digit long."
exit 8
fi
if [ ${DEVNOLEN} -gt 4 ]; then
echo "The device number may only be 4 digits long."
exit 9
fi
if [ ${DEVNOLEN} -lt 4 ]; then
DEVNO=$(echo "0000${DEVNO}" | rev | cut -c1-4 | rev)
fi
BUSID="${FIRST}.${SECOND}.${DEVNO}"
if [ ! -h /sys/bus/ccw/devices/${BUSID} ]; then
echo "Busid ${BUSID} was not found."
/usr/sbin/cio_ignore -i ${BUSID} > /dev/null
if [ $? -eq 0 ]; then
echo "That device is in the cio_ignore list."
echo "Please remove it with \"cio_ignore -r ${BUSID}\" before trying again."
fi
exit 10
fi
case ${DEVNO:0:3} in
019) if grep -q "version = FF" /proc/cpuinfo 2>/dev/null; then
echo "That looks like a CMS disk."
if [ ${FORCE} -eq 0 ]; then
echo "Specify the -f option to force the operation."
exit 11
fi
echo "But you specified -f so we'll kill it anyway."
fi
;;
esac
read ORIG_ONLINE_STATUS < /sys/bus/ccw/devices/${BUSID}/online
DISCIPLINE="none"
if [ -r /sys/bus/ccw/devices/${BUSID}/discipline ]; then
# We have to bring the device online before the kernel will fill in
# the value for discipline.
if [ ${ORIG_ONLINE_STATUS} -eq 0 ]; then
/usr/sbin/chccwdev -e ${BUSID}
/usr/sbin/udevadm settle
fi
read STATUS < /sys/bus/ccw/devices/${BUSID}/status
if [ "${STATUS}" == "unformatted" ]; then
echo "DASD device ${BUSID} is already in an unformatted state."
if [ ${ORIG_ONLINE_STATUS} -eq 0 ]; then
/usr/sbin/chccwdev -d -s ${BUSID}
/usr/sbin/udevadm settle
fi
exit 0
fi
read DISCIPLINE < /sys/bus/ccw/devices/${BUSID}/discipline
else read CU_TYPE < /sys/bus/ccw/devices/${BUSID}/cutype
read DEV_TYPE < /sys/bus/ccw/devices/${BUSID}/devtype
case "${CU_TYPE}" in
3990/*|2105/*|2107/*|1750/*|9343/*)
DISCIPLINE=ECKD
;;
3880/*)
case "${DEV_TYPE}" in
3390/*)
DISCIPLINE=ECKD
;;
esac
;;
esac
fi
if [ "${DISCIPLINE}" != "ECKD" ]; then
echo "This script only works on ECKD DASD."
if [ ${ORIG_ONLINE_STATUS} -eq 0 ]; then
/usr/sbin/chccwdev -d -s ${BUSID}
fi
exit 12
fi
read STATUS < /sys/bus/ccw/devices/${BUSID}/online
if [ ${STATUS} -eq 1 ]; then
if [ ! -h /dev/disk/by-path/ccw-${BUSID} ]; then
echo "The udev-generated symbolic link in /dev/disk/by-path was not found."
exit 13
fi
/usr/sbin/chccwdev -d -s ${BUSID}
/usr/sbin/udevadm settle
read STATUS < /sys/bus/ccw/devices/${BUSID}/online
if [ ${STATUS} -ne 0 ]; then
echo "Device number ${DEVNO} didn't go offline. Unable to continue."
exit 14
fi
fi
/usr/sbin/chccwdev -a raw_track_access=1 -e ${BUSID}
/usr/sbin/udevadm settle
read STATUS < /sys/bus/ccw/devices/${BUSID}/online
if [ ${STATUS} -ne 1 ]; then
echo "Unable to bring ${DEVNO} online. Unable to continue."
exit 15
fi
# After this point, we will kill the formatting on the device
perl -e 'for ($h=0;$h<2;$h++){printf "\0\0\0%c\0\0\0\x8%s",$h,(("\0"x8).("\xff"x8).("\0"x65512))}' | dd bs=65536 count=2 oflag=direct of=/dev/disk/by-path/ccw-${BUSID} >/dev/null 2>&1
if [ "$?" -ne 0 ]; then
echo "The writing of the null record 0 failed."
exit 16
fi
echo "Setting ${BUSID} back offline with raw track access disabled."
/usr/sbin/chccwdev -d -s -a raw_track_access=0 ${BUSID}
/usr/sbin/udevadm settle
if [ ${ORIG_ONLINE_STATUS} -eq 1 ]; then
/usr/sbin/chccwdev -e ${BUSID}
/usr/sbin/udevadm settle
fi

217
killcdl.suse Normal file
View File

@ -0,0 +1,217 @@
#!/bin/sh
#
# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
# Released under the GNU General Public License version 2.
#
let FORCE=0
DEVPARM=""
usage(){
echo "Usage: ${0} [ -f ] devno|busid"
echo " -f Force unformatting for DASD volumes in the CMS device range of 19x."
echo " devno The \"plain\" device number of the volume, e.g. 3184."
echo " busid The full specification of the volume, e.g., 0.0.3184."
}
ARCH="$(/bin/uname -m)"
if [ "${ARCH}" != "s390x" ] && [ "${ARCH}" != "s390" ]; then
echo "This script is only useful on IBM mainframes."
exit 1
fi
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt -a --options f -n "killcdl" -- "$@")
if [ $? -ne 0 ]; then
usage
exit 3
fi
eval set -- "${ARGS}"
for ARG; do
case "${ARG}" in
-f) FORCE=1
shift 1
;;
--) shift 1
;;
[0-9a-fA-F]*) if [ ! -z "${DEVPARM}" ]; then
echo "More than one parameter specified."
usage
exit 4
fi
DEVPARM=${1}
shift 1
;;
*) echo "That looks invalid"
usage
exit 5
;;
esac
done
if [ -z "${DEVPARM}" ]; then
echo "You must specify the device number of the DASD volume to be unformatted."
usage
exit 6
fi
DEVNO=$(echo "${DEVPARM}" | tr A-Z a-z)
# Validate the device number or busid provided
set -- $(IFS='.'; echo ${DEVNO})
let NUMPARMS=${#}
if [ ${NUMPARMS} -ne 1 ] && [ ${NUMPARMS} -ne 3 ]; then
echo "You have not specified the device number in a recognizable format."
echo "It must either be the plain device number, e.g., 0123, or in"
echo "so-called busid format, e.g., 0.0.0123"
exit 7
fi
# Just a device number, SIMPLE=1. A busid, SIMPLE=0
SIMPLE=0
if [ ${NUMPARMS} -eq 1 ]; then
let SIMPLE=1
let FIRST=0
let FIRSTLEN=1
let SECOND=0
let SECONDLEN=1
DEVNO="${1}"
let DEVNOLEN=${#1}
else FIRST="${1}"
let FIRSTLEN=${#FIRST}
SECOND="${2}"
let SECONDLEN=${#SECOND}
DEVNO="${3}"
let DEVNOLEN=${#3}
fi
if [ ${FIRSTLEN} -ne 1 ] || [ ${SECONDLEN} -ne 1 ]; then
echo "The first and second fields of the busid may only be one digit long."
exit 8
fi
if [ ${DEVNOLEN} -gt 4 ]; then
echo "The device number may only be 4 digits long."
exit 9
fi
if [ ${DEVNOLEN} -lt 4 ]; then
DEVNO=$(echo "0000${DEVNO}" | rev | cut -c1-4 | rev)
fi
BUSID="${FIRST}.${SECOND}.${DEVNO}"
if [ ! -h /sys/bus/ccw/devices/${BUSID} ]; then
echo "Busid ${BUSID} was not found."
/sbin/cio_ignore -i ${BUSID} > /dev/null
if [ $? -eq 0 ]; then
echo "That device is in the cio_ignore list."
echo "Please remove it with \"cio_ignore -r ${BUSID}\" before trying again."
fi
exit 10
fi
case ${DEVNO:0:3} in
019) if grep -q "version = FF" /proc/cpuinfo 2>/dev/null; then
echo "That looks like a CMS disk."
if [ ${FORCE} -eq 0 ]; then
echo "Specify the -f option to force the operation."
exit 11
fi
echo "But you specified -f so we'll kill it anyway."
fi
;;
esac
read ORIG_ONLINE_STATUS < /sys/bus/ccw/devices/${BUSID}/online
DISCIPLINE="none"
if [ -r /sys/bus/ccw/devices/${BUSID}/discipline ]; then
# We have to bring the device online before the kernel will fill in
# the value for discipline.
if [ ${ORIG_ONLINE_STATUS} -eq 0 ]; then
/sbin/chccwdev -e ${BUSID}
/sbin/udevadm settle
fi
read STATUS < /sys/bus/ccw/devices/${BUSID}/status
if [ "${STATUS}" == "unformatted" ]; then
echo "DASD device ${BUSID} is already in an unformatted state."
if [ ${ORIG_ONLINE_STATUS} -eq 0 ]; then
/sbin/chccwdev -d -s ${BUSID}
/sbin/udevadm settle
fi
exit 0
fi
read DISCIPLINE < /sys/bus/ccw/devices/${BUSID}/discipline
else read CU_TYPE < /sys/bus/ccw/devices/${BUSID}/cutype
read DEV_TYPE < /sys/bus/ccw/devices/${BUSID}/devtype
case "${CU_TYPE}" in
3990/*|2105/*|2107/*|1750/*|9343/*)
DISCIPLINE=ECKD
;;
3880/*)
case "${DEV_TYPE}" in
3390/*)
DISCIPLINE=ECKD
;;
esac
;;
esac
fi
if [ "${DISCIPLINE}" != "ECKD" ]; then
echo "This script only works on ECKD DASD."
if [ ${ORIG_ONLINE_STATUS} -eq 0 ]; then
/sbin/chccwdev -d -s ${BUSID}
fi
exit 12
fi
read STATUS < /sys/bus/ccw/devices/${BUSID}/online
if [ ${STATUS} -eq 1 ]; then
if [ ! -h /dev/disk/by-path/ccw-${BUSID} ]; then
echo "The udev-generated symbolic link in /dev/disk/by-path was not found."
exit 13
fi
/sbin/chccwdev -d -s ${BUSID}
/sbin/udevadm settle
read STATUS < /sys/bus/ccw/devices/${BUSID}/online
if [ ${STATUS} -ne 0 ]; then
echo "Device number ${DEVNO} didn't go offline. Unable to continue."
exit 14
fi
fi
/sbin/chccwdev -a raw_track_access=1 -e ${BUSID}
/sbin/udevadm settle
read STATUS < /sys/bus/ccw/devices/${BUSID}/online
if [ ${STATUS} -ne 1 ]; then
echo "Unable to bring ${DEVNO} online. Unable to continue."
exit 15
fi
# After this point, we will kill the formatting on the device
perl -e 'for ($h=0;$h<2;$h++){printf "\0\0\0%c\0\0\0\x8%s",$h,(("\0"x8).("\xff"x8).("\0"x65512))}' | dd bs=65536 count=2 oflag=direct of=/dev/disk/by-path/ccw-${BUSID} >/dev/null 2>&1
if [ "$?" -ne 0 ]; then
echo "The writing of the null record 0 failed."
exit 16
fi
echo "Setting ${BUSID} back offline with raw track access disabled."
/sbin/chccwdev -d -s -a raw_track_access=0 ${BUSID}
/sbin/udevadm settle
if [ ${ORIG_ONLINE_STATUS} -eq 1 ]; then
/sbin/chccwdev -e ${BUSID}
/sbin/udevadm settle
fi

335
lgr_check Normal file
View File

@ -0,0 +1,335 @@
#!/bin/sh
function check_sysoper(){
local SYSOPER=$(vmcp q sysoper | cut -f4 -d" ")
local USERID=$(vmcp q userid | cut -f1 -d" ")"."
if [ "${SYSOPER}" == "${USERID}" ]; then
return 0
else return 1
fi
}
function check_disc(){
local USERID=$(vmcp q userid | cut -f1 -d" ")
local DISCONNECTED=$(vmcp q ${USERID} | cut -f2 -d-)
if [ "${DISCONNECTED}" == " DSC" ]; then
return 1
else return 0
fi
}
function check_3270(){
local CONMODE=$(vmcp q term | sed -n -e '/CONMODE/ {s/CONMODE \([0-9]*\), .*$/\1/;p}')
if [ "${CONMODE}" == "3270" ]; then
return 0
else return 1
fi
}
function check_graf(){
local GRAF
GRAF=$(vmcp -b 1048576 q v graf 2>/dev/null | grep -v "^CONS" | grep "ON LDEV" )
if [ ${?} -eq 0 ] && [ -n "${GRAF}" ]; then
return 0
else return 1
fi
}
function check_ascii_console(){
local SYSASCII=$(vmcp q v sysascii 2>/dev/null | grep "not attached to you")
if [ -z "${SYSASCII}" ]; then
return 0
else return 1
fi
}
function check_tdisk(){
local TDISK=$(vmcp -b 1048576 q v dasd 2>/dev/null | grep TEMP)
if [ -n "${TDISK}" ]; then
return 0
else return 1
fi
}
function check_ctc(){
local CTC
CTC=$(vmcp -b 1048576 q v ctc 2>/dev/null)
if [ ${?} -eq 0 ]; then
return 0
else return 1
fi
}
function check_dynamic_switch(){
local SWCH
SWCH=$(vmcp -b 1048576 q v switches 2>/dev/null)
if [ ${?} -eq 0 ]; then
return 0
else return 1
fi
}
function check_maint_mdisks(){
local MDISKS
MDISKS=$(vmcp -b 1048576 q v dasd | grep -E "0190|0191|0193|019D|019E")
if [ -n "${MDISKS}" ]; then
return 0
else return 1
fi
}
function check_wrkalleg(){
local WRKALLEG
WRKALLEG=$(vmcp -b 1048576 q wrkalleg | grep "is not simulated")
if [ -z "${WRKALLEG}" ]; then
return 0
else return 1
fi
}
function check_isolated_vswitch(){
local ISOLATED=0
local VSWITCH
# Find out if we have any NICs coupled to any VSWITCH or not. If not, we're OK.
VSWITCH=$(vmcp -b 1048576 q nic | sed -e '1~2 {N;s/\n//;}' | grep VSWITCH)
if [ -z "${VSWITCH}" ]; then
return 1
fi
ISOLATED=$(vmcp -b 1048576 q nic | sed -e '1~2 {N;s/\n//;}' | \
grep VSWITCH | \
sed -e 's/^.* VSWITCH: //' | \
while read owner name
do VSWITCH=$(vmcp -b 1048576 q vswitch $name | grep RDEV)
if [ -z "${VSWITCH}" ]; then
echo 1
fi
done)
if [ "${ISOLATED}" == "1" ]; then
return 0
else return 1
fi
}
function check_chpidvirt(){
local CHPIDV
CHPIDV=$(vmcp q chpidv 2>/dev/null | grep "CHPID Virtualization is on")
if [ -z "${CHPIDV}" ]; then
return 0
else return 1
fi
}
function check_pci_functions(){
local PCIF
local RETCODE
PCIF=$(vmcp -b 1048576 q v pcif 2>/dev/null | grep "A PCI function was not found.")
RETCODE=${?}
if [ ${RETCODE} -eq 0 ] && [ -z "${PCIF}" ]; then
return 0
else return 1
fi
}
function check_tape_assign(){
local TAPES
local RETCODE=1
TAPES=$(vmcp -b 1048576 q v tapes 2>/dev/null | grep "Device TAPE does not exist")
if [ -n "${TAPES}" ]; then
return 1
fi
TAPES=$(vmcp -b 1048576 q v tapes 2>/dev/null | grep "NOASSIGN")
if [ -n "${TAPES}" ]; then
return 0
else return 1
fi
}
function check_open_spool(){
local QSPOOL
local OPENSPOOL=0
QSPOOL=$(vmcp -b 1048576 q pun \* all 2>/dev/null | grep "OPEN")
if [ -n "${QSPOOL}" ]; then
let OPENSPOOL=1
fi
QSPOOL=$(vmcp -b 1048576 q prt \* all 2>/dev/null | grep "OPEN" | grep -v " CON ")
if [ -n "${QSPOOL}" ]; then
let OPENSPOOL=1
fi
if [ ${OPENSPOOL} -eq 1 ]; then
return 0
else return 1
fi
}
function check_xstore(){
local XSTOR
XSTOR=$(vmcp -b 1048576 q v xstor 2>/dev/null | grep "XSTORE = none")
if [ -z "${XSTOR}" ]; then
return 0
else return 1
fi
}
function check_iucv(){
local QIUCV
QIUCV=$(vmcp -b 1048576 q iucv 2>/dev/null | grep -vE "^No IUCV paths exist|^Source| *MSG| *MSGALL")
if [ -n "${QIUCV}" ]; then
return 0
else return 1
fi
}
function usage(){
echo "Usage: ${0} [ -f ] [ -h ] devno|busid"
echo " -q Don't generate any output, just set a return code."
echo " -m Suppress the check for local minidisks."
echo " Only use this if you know for certain all minidisks for this"
echo " guest are NOT local to this instance of z/VM."
echo " -h Display this help message."
}
ARCH="$(/bin/uname -m)"
if [ "${ARCH}" != "s390x" ] && [ "${ARCH}" != "s390" ]; then
echo "This script is only useful on IBM mainframes."
exit 1
fi
HYPERVISOR=$(systemd-detect-virt)
if [ "${HYPERVISOR}" != "zvm" ]; then
echo "This script is only useful for guests of the z/VM hypervisor."
exit 1
fi
MDISK_SUPPRESS=0
msg="echo"
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt -a --options qhm -n "lgr_check" -- "$@")
if [ $? -ne 0 ]; then
usage
exit 3
fi
eval set -- "${ARGS}"
for ARG; do
case "${ARG}" in
-h) usage;
exit 0
;;
-m) let MDISK_SUPPRESS=1;
shift 1
;;
-q) msg="/bin/true"
shift 1
;;
--) shift 1
;;
*) ${msg} "Extraneous input detected: ${1}"
shift 1
;;
esac
done
let FAIL=0
##let COLS=$(stty -a | sed -n -e '/columns/{s/^.*columns \([0-9]*\);.*$/\1/;p}')
if [ ! -c /dev/vmcp ]; then
${msg} "Cannot find /dev/vmcp to issue z/VM CP commands."
exit 1
fi
${msg} "Checking for conditions that might prevent Live Guest Relocation"
if check_chpidvirt; then
${msg} "This guest does not have CHPID Virtualization set for it in the CP directory."
${msg} "Live Guest Relocation is absolutely not possible for this guest."
# exit 99
let FAIL=1
fi
if check_sysoper ; then
${msg} "This guest is currently the z/VM system operator."
let FAIL=1
fi
let GUEST_CONN=0
if check_disc; then
${msg} "The guest is not running disconnected."
let GUEST_CONN=1
let FAIL=1
fi
if check_3270; then
${msg} -n "The guest has a 3270 console, "
if [ ${GUEST_CONN} -eq 0 ]; then
${msg} "but it is not currently in use."
else ${msg} "and it is currently in use."
let FAIL=1
fi
fi
if check_graf; then
${msg} "The guest has a DIALED 3270 device in current use."
let FAIL=1
fi
if check_ascii_console; then
${msg} "The guest has the ASCII console attached to it."
let FAIL=1
fi
if check_tdisk; then
${msg} "The guest has a temporary disk (T-disk) attached to it."
let FAIL=1
fi
if check_ctc; then
${msg} "The guest has a Channel-to-Channel device (CTC) attached to it."
let FAIL=1
fi
if check_dynamic_switch; then
${msg} "The guest has a dynamic switching device attached to it."
let FAIL=1
fi
if check_wrkalleg; then
${msg} "The guest is currently using virtual working allegiance."
let FAIL=1
fi
if [ ${MDISK_SUPPRESS} -eq 0 ] && check_maint_mdisks; then
${msg} "The guest currently has one or more Minidisks that might be local to this instance of z/VM."
let FAIL=1
fi
if check_isolated_vswitch; then
${msg} "The guest is currently coupled to an isolated VSWITCH."
let FAIL=1
fi
if check_pci_functions; then
${msg} "The guest has PCI functions available to it."
let FAIL=1
fi
if check_tape_assign; then
${msg} "The guest has potential problems with a tape."
let FAIL=1
fi
if check_open_spool; then
${msg} "The guest has an open SPOOL file that is not from the virtual console."
let FAIL=1
fi
if check_xstore; then
${msg} "The guest has Expanded Storage attached to it."
let FAIL=1
fi
if check_iucv; then
${msg} "The guest has an IUCV connection to a z/VM system service or another z/VM user."
let FAIL=1
fi
if [ ${FAIL} == 1 ]; then
${msg} "The guest is currently not eligible for Live Guest Relocation."
exit 1
else ${msg} "As far as can be determined from within the guest, it is currently eligible for Live Guest Relocation."
${msg} "This is not a guarantee. Other factors that cannot be checked from within the guest may prevent it from being eligible for LGR."
fi

72
mkdump.8 Normal file
View File

@ -0,0 +1,72 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
.TH MKDUMP "8" "August 2011" "mkdump 2.0" "System Administration Utilities"
.SH NAME
mkdump \- Preparing disks for use as S/390 dump device.
.SH SYNOPSIS
.B mkdump
[\fIOPTIONS\fR] [\fIDEVICE\fR]...
.SH DESCRIPTION
mkdump 2.0.3
.PP
Prepare one or more volumes for use as S/390 dump device. Supported devices
are ECKD DASD and SCSI over zFCP disks, while multi\-volumes are limited to DASD.
.PP
Only whole disks can be used, no partitions! If the device is incompatible
formatted/partioned, the script will refuse to install the dump record
unless the \fB\-\-force\fR switch is given.
.PP
Disks which are in use or have mounted partitions will not be listed and can't be used.
The mentioning of "dumpdevice" after a disk indicates that it is an already usable dump device. Additionally multi\-volume dump devices are indicated by the list of including DASD ids.
.SH OPTIONS
.TP
\fB\-h\fR, \fB\-\-help\fR
display this help and exit
.TP
\fB\-V\fR, \fB\-\-version\fR
display version information and exit
.TP
\fB\-d\fR, \fB\-\-debug\fR
debug mode, do not run programs which commit changes
.TP
\fB\-v\fR, \fB\-\-verbose\fR
be verbose and show command outputs
.TP
\fB\-f\fR, \fB\-\-force\fR
force overwrite of the disk
.TP
\fB\-l\fR, \fB\-\-list\-dump\fR
display dump disks
.TP
\fB\-D\fR, \fB\-\-list\-dasd\fR
display usable DASD disks (Device, Size, ID, Dump)
.TP
\fB\-Z\fR, \fB\-\-list\-zfcp\fR
display usable SCSI over zFCP disks (Device, Size, ID, WWPN, LUN, Dump)
.SH DIAGNOSTICS
mkdump returns the following exit codes:
.RS
.IP 0
Normal (no errors or warnings detected)
.IP 11
Invalid or unusable disk (fatal)
.IP 12
Incompatible formatting/partitioning, can be corrected with --force
.IP 13
Missing support programs
.IP 14
Bad command line parameters
.IP 15
Access problem
.IP other
Support program failed
.SH AUTHOR
Written by Tim Hardeck <thardeck@suse.de>.
.SH "REPORTING BUGS"
Report bugs on https://bugzilla.novell.com/
.SH COPYRIGHT
Copyright \(co 2011 SUSE LINUX Products GmbH
License GPLv2 or (at your option) any later version.
<http://www.gnu.org/licenses/gpl-2.0.html>
.br
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

666
mkdump.pl.opensuse Normal file
View File

@ -0,0 +1,666 @@
#!/usr/bin/perl
########################################################################
#
# mkdump.pl - Preparing disks for use as S/390 dump device
#
# Copyright (c) 2011 Tim Hardeck, SUSE LINUX Products GmbH
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
# Based on mkdump.sh (c) 2004 Hannes Reinecke, SuSE AG
#
# License:
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
########################################################################
use strict;
use warnings;
use Fcntl;
use Getopt::Long;
my $VERSION = "2.0.4";
my $BLKID = "/usr/sbin/blkid";
my $PARTED = "/usr/sbin/parted";
my $FDASD = "/usr/sbin/fdasd";
my $DASDVIEW = "/usr/sbin/dasdview";
my $DASDFMT = "/usr/sbin/dasdfmt";
my $ZIPL = "/usr/sbin/zipl";
my $UDEVADM = "/usr/sbin/udevadm";
my $ZGETDUMP = "/usr/sbin/zgetdump";
# temporary DASD device configuration file for Zipl
my $MDPATH = "/tmp/mvdump.conf.".`mcookie`;
chomp($MDPATH);
my $OPT_DEBUG = 0;
my $OPT_FORCE = 0;
my $OPT_VERBOSE = 0;
sub cleanup
{
# DASD
if (-e $MDPATH) {
system("rm -f $MDPATH");
}
}
sub exit_with
{
my $message = shift();
my $exitcode = shift();
print STDERR "$message Exiting...\n";
cleanup();
# fdasd isn't able to create volume label interactively
# could be fixed with a reformat
if ($exitcode == 65280) {
$exitcode = 12;
}
# bigger exit codes are not supported
if ($exitcode > 255) {
$exitcode = 255;
}
exit($exitcode);
}
sub run_cmd
{
my $cmd = shift();
my $output = "";
if (! $OPT_DEBUG) {
my ($app) = $cmd =~ /\/(\w+) /;
# run command
$output = `$cmd`;
my $exit_code = $?;
# wait for udev to finish processing
system("$UDEVADM settle");
# only print output in case of an error or in verbose mode
if ($output and ($exit_code != 0 or $OPT_VERBOSE)) {
print("$output\n");
}
if ($exit_code != 0) {
exit_with("$app failed with exit code $exit_code", $exit_code);
}
} else {
# only print the command in debug mode
print("\`$cmd\`\n");
}
return($output);
}
sub check_paths
{
for my $path ($BLKID, $PARTED, $FDASD, $DASDVIEW, $DASDFMT, $ZIPL, $UDEVADM, $ZGETDUMP) {
unless ( -x $path) {
exit_with("Command $path is not available.", 13);
}
}
}
sub read_file
{
my $path = shift();
open(my $file, "<", "$path") or exit_with("Unable to access $path: $!.", 15);
my @content = <$file>;
close($file);
# no need for arrays in case of single lines
if (@content > 1) {
return @content;
} else {
chomp($content[0]);
return($content[0]);
}
}
sub is_dasd
{
# remove leading /dev/
my $device = substr(shift(), 5);
if (-r "/sys/block/$device/device/discipline") {
return(1);
} else {
return(0);
}
}
sub has_free_single_kpartx
{
my $device = substr(shift(), 5);
return(0) unless ($device =~ /^dm-[0-9]+$/);
my $blockpath = "/sys/block/$device";
my @holders = glob("$blockpath/holders/*");
return(0) unless (@holders == 1);
my $dmuuid = read_file("$holders[0]/dm/uuid");
return(0) unless ($dmuuid =~ /^part1-mpath-/);
my @holderparts = split(/\//, $holders[0]);
my $holder = "/dev/" . $holderparts[-1];
if(-b $holder and sysopen(my $blockdev, $holder, O_RDWR|O_EXCL)) {
close($blockdev);
return(1);
}
return(0);
}
sub is_zfcp
{
# remove leading /dev/
my $device = substr(shift(), 5);
my $blockpath = "/sys/block/$device";
my $dmname = undef;
# if user passed a device name on cmdline that we listed before
# convert to a dm-[0-9]+ kernel device name
if ($device =~ /^mapper\//) {
$device = substr(readlink("/dev/" . $device), 3);
$blockpath = "/sys/block/" . $device;
}
# check if dm-multipath and get one path member
if ($device =~ /^dm-[0-9]+$/) {
my $dmuuid = read_file("$blockpath/dm/uuid");
return(undef) unless $dmuuid =~ /^mpath-/;
$dmname = read_file("$blockpath/dm/name");
opendir(DIR, "$blockpath/slaves/") or return(undef);
while (defined(my $pathmember = readdir(DIR))) {
# skip ".", "..", or other non scsi disk entries
next unless $pathmember =~ /^sd[a-z]+$/;
$device = $pathmember;
last;
}
closedir(DIR);
}
my $devpath = "/sys/block/$device/device";
unless (-r "$devpath/hba_id" or -r "$devpath/type") {
return(undef);
}
my $devtype = read_file("$devpath/type");
# SCSI type '0' means disk
if ($devtype == 0) {
if (defined $dmname) {
return("/dev/mapper/$dmname");
} else {
return("/dev/$device");
}
} else {
return(undef);
}
}
sub get_partition_num
{
# remove leading /dev/
my $device = substr(shift, 5);
my $part_num = grep(/\s+$device\d+/, read_file("/proc/partitions"));
return($part_num);
}
sub print_device
{
my $device = shift();
my $only_dump_disks = shift();
my $devpath;
if ($device =~ /^\/dev\/mapper\//) {
$devpath = "/sys/block/" . substr(readlink($device), 3);
} else {
$devpath = "/sys/block/" . substr($device, 5);
}
my $output = $device;
my $dump_device = 0;
my $size = int(read_file("$devpath/size") / 2048); # 512 Byte blocks
# size can't be read this way in case of unformatted devices
if ($size != 0) {
$output .= "\t${size}MB";
} else {
$output .= "\tunknown";
}
if (is_dasd($device)) {
my ($busid) = readlink("$devpath/device") =~ /(\w\.\w\.\w{4})/;
$output .= "\t$busid";
# check for dump record and list multi volumes
my $zgetdump_output = `$ZGETDUMP -d $device 2>&1`;
my @dump_devs = $zgetdump_output =~ /(\w\.\w\.\w{4})/g;
if (@dump_devs) {
$dump_device = 1;
$output .= "\tdumpdevice";
# no need to output the dump ids for a single device
if (@dump_devs > 1) {
for my $id (@dump_devs) {
$output .= "|$id";
}
}
} else {
# check for single volume dump devices
if ($zgetdump_output =~ /Single-volume DASD dump tool/) {
$dump_device = 1;
$output .= "\tdumpdevice";
}
}
} else {
# get one path member to fill path info for "yast onpanic"
if ($device =~ /^\/dev\/mapper\//) {
my $blockdev = substr(readlink($device), 3);
my $blockpath = "/sys/block/" . $blockdev;
opendir(DIR, "$blockpath/slaves/") or return(undef);
while (defined(my $pathmember = readdir(DIR))) {
# skip ".", "..", or other non scsi disk entries
next unless $pathmember =~ /^sd[a-z]+$/;
$devpath = "/sys/block/" . $pathmember;
last;
}
closedir(DIR);
}
my $adapter = read_file("$devpath/device/hba_id");
my $wwpn = read_file("$devpath/device/wwpn");
my $lun = read_file("$devpath/device/fcp_lun");
$output .= "\t$adapter\t$wwpn\t$lun";
# check for dump record
my $zgetdump = `$ZGETDUMP -d $device 2>&1`;
if ($? == 0) {
my ($dsize) = ($zgetdump =~ /Maximum dump size\.:\s+([0-9]+) MB/m);
$dsize = $size unless (defined($dsize));
$output = "$device\t${dsize}MB\t$adapter\t$wwpn\t$lun\tdumpdevice";
$dump_device = 1;
}
}
if ($only_dump_disks) {
if ($dump_device) {
print("$output\n");
}
} else {
print("$output\n");
}
}
sub list_free_disks
{
my $devices_ref = shift();
my $type = shift();
if (@$devices_ref) {
for my $device (@$devices_ref) {
print_device($device);
}
} else {
print STDERR "No free $type devices available!\n";
}
}
sub list_dump_disks
{
my @devices = @_;
if (@devices) {
for my $device (@devices) {
print_device($device, 1);
}
} else {
print STDERR "No dump devices available!\n";
}
}
sub determine_free_disks
{
my @dasd;
my @zfcp;
my @devices;
# gather block devices
my $path="/sys/block/";
opendir(DIR, $path) or exit_with("Unable to find $path: $!", 15);
while (defined(my $file = readdir(DIR))) {
# no need to add other devices then dasd* or sd*
# or dm-multipath
if ($file =~ /^dasd[a-z]+$/ or $file =~ /^sd[a-z]+$/ or
$file =~ /^dm-[0-9]+$/) {
push(@devices, $file);
}
}
closedir(DIR);
for my $entry (@devices) {
# only allow disks, no partitions
my ($device) = $entry =~ /^([a-z]+)$/;
# dm devices other than dm-multipath are filtered by is_zfcp()
($device) = $entry =~ /^(dm-[0-9]+)$/ unless ($device);
next unless ($device);
$device = "/dev/$device";
# determine if the block device could be accessed exclusively
if(-b $device and sysopen(my $blockdev, $device, O_RDWR|O_EXCL)) {
close($blockdev);
if (is_dasd($device)) {
push(@dasd, $device);
}
my $zfcp = is_zfcp($device);
if (defined $zfcp) {
push(@zfcp, $zfcp);
}
} else {
# A dm-multipath device with a single holder
# being a kpartx partition number 1 could still
# be free or contain a zfcpdump boot record.
# Due to the kpartx linear dm mapping, such
# dm-multipath device cannot open exclusively.
if (has_free_single_kpartx($device)) {
my $zfcp = is_zfcp($device);
if (defined $zfcp) {
push(@zfcp, $zfcp);
}
}
}
# wait for udev to process all events triggered by sysopen(,O_EXCL)
system("$UDEVADM settle");
}
return(\@dasd, \@zfcp);
}
sub prepare_dasd
{
my @devices = @_;
my $format_disks = "";
# check formatting
for my $device (@devices) {
# determine disk layout
my ($fmtstr) = `$DASDVIEW -x $device` =~ /(\w\w\w) formatted/;
SWITCH:
for($fmtstr) {
if (/NOT/) {
print("Unformatted disk, formatting $device.\n");
$format_disks .= " $device";
last SWITCH;
}
if (/LDL/) {
if ($OPT_FORCE) {
print("Linux disk layout, reformatting $device.\n");
$format_disks .= " $device";
} else {
print("$device was formatted with the Linux disk layout.\n");
print("Unable to use it without reformatting.\n");
exit_with("Re-issue the mkdump command with the --force option.", 12);
}
last SWITCH;
}
if (/CDL/) {
# allow reformatting with force, since fdasd isn't able to create volume label interactively
if ($OPT_FORCE) {
print("Compatible disk layout, force reformatting $device.\n");
$format_disks .= " $device";
} else {
print("$device: Compatible disk layout, Ok to use.\n");
}
last SWITCH;
}
exit_with("Unknown layout ($fmtstr), cannot use disk.", 11);
}
}
# format devices
if ($format_disks) {
#up to eight devices in parallel
run_cmd("$DASDFMT -P 8 -b 4096 -y -f $format_disks");
}
# check partitioning and partition
for my $device (@devices) {
my $part_num = get_partition_num($device);
if ($part_num == 0 or $OPT_FORCE) {
print("Re-partitioning disk $device.\n");
run_cmd("$FDASD -a $device");
} else {
# allow disk with one partition if it don't consist a file system
if ($part_num == 1) {
my ($fstype) = `$BLKID ${device}1` =~ /TYPE=\"(\w+)\"/;
if ($fstype) {
exit_with("Device ${device}1 already contains a filesystem of type $fstype.", 12);
}
} else {
exit_with("$part_num partitions detected, cannot use disk $device.", 12);
}
}
}
}
sub setup_dasddump
{
my @devices = @_;
prepare_dasd(@devices);
# create zipl device configuration file
# don't create files in debug mode
unless ($OPT_DEBUG) {
open(my $file, ">", $MDPATH) or exit_with("Unable to access $MDPATH: $!.", 15);
for my $device (@devices) {
print{$file}("${device}1\n");
}
close($file);
}
print("Creating dump record.\n");
run_cmd("${ZIPL} -V -n -M $MDPATH");
cleanup();
}
sub setup_zfcpdump
{
my $device = shift();
# check partitioning
my $part_num = get_partition_num($device);
if ($part_num == 0 or $OPT_FORCE) {
print("Re-partitioning disk $device.\n");
run_cmd("$PARTED -s -- $device mklabel gpt mkpart primary 0 -1");
} else {
if ($part_num > 1) {
exit_with("$part_num partitions detected, cannot use disk $device.", 12);
}
}
# install bootloader
print("Creating dump record.\n");
my $partdev;
if ($device =~ /^\/dev\/mapper\//) {
$partdev = $device . "-part1"; # kpartx partition on multipath
} else {
$partdev = $device . "1"; # real partition, single path SCSI
}
run_cmd("${ZIPL} -V -d ${partdev}");
cleanup();
}
sub print_version
{
print << "EOF";
mkdump $VERSION
Copyright (c) 2011 SUSE LINUX Products GmbH
License GPLv2 or (at your option) any later version.
<http://www.gnu.org/licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Tim Hardeck <thardeck\@suse.de>.
EOF
exit(0);
}
sub print_usage
{
my $exitcode = shift();
print << "EOF";
Usage: mkdump [OPTIONS] [DEVICE]...
mkdump $VERSION
Prepare one or more volumes for use as S/390 dump device. Supported devices
are ECKD DASD and SCSI over zFCP disks, while multi-volumes are limited to DASD.
Only whole disks can be used, no partitions! If the device is incompatible
formatted/partioned, the script will refuse to install the dump record
unless the --force switch is given.
Disks which are in use or have mounted partitions will not be listed and can't be used.
The mentioning of "dumpdevice" after a disk indicates that it is an already usable dump device. Additionally multi-volume dump devices are indicated by the list of including DASD ids.
Options:
-h, --help display this help and exit
-V, --version display version information and exit
-d, --debug debug mode, do not run programs which commit changes
-v, --verbose be verbose and show command outputs
-f, --force force overwrite of the disk
-l, --list-dump display dump disks
-D, --list-dasd display usable DASD disks (Device, Size, ID, Dump)
-Z, --list-zfcp display usable SCSI over zFCP disks (Device, Size, ID, WWPN, LUN, Dump)
Report bugs on https://bugzilla.novell.com/
EOF
exit($exitcode);
}
sub analyze_cmd_parameters
{
#verbose, debug and force are global
my $opt_help = 0;
my $opt_version = 0;
my $opt_dump = 0;
my $opt_dasd = 0;
my $opt_zfcp = 0;
if (@ARGV == 0) {
print_usage(14);
}
Getopt::Long::Configure('bundling');
GetOptions(
'h|help' => \$opt_help,
'V|version' => \$opt_version,
'd|debug' => \$OPT_DEBUG,
'v|verbose' => \$OPT_VERBOSE,
'f|force' => \$OPT_FORCE,
'l|list-dump' => \$opt_dump,
'D|list-dasd' => \$opt_dasd,
'Z|list-zfcp' => \$opt_zfcp,
) or print_usage(14);
if ($opt_help) {
print_usage(0);
}
if ($opt_version) {
print_version();
}
# determine free dasd and zfcp devices
my ($dasd_ref, $zfcp_ref) = determine_free_disks();
if ($opt_dump) {
list_dump_disks(@$dasd_ref, @$zfcp_ref);
exit 0;
}
if ($opt_dasd) {
list_free_disks(\@$dasd_ref, "dasd");
}
if ($opt_zfcp) {
list_free_disks(\@$zfcp_ref, "zfcp");
}
# allow listing of both device types at the same time
if ($opt_dasd or $opt_zfcp) {
exit 0;
}
# check provided devices and be strict
my @devices;
for my $device (@ARGV) {
if (grep(/$device/, @devices)) {
exit_with("$device is mentioned more than once.", 14);
}
# dm devices other than dm-multipath are filtered by is_zfcp()
if ( $device =~ /^\/dev\/[a-z]+$/ == 0 and
$device !~ /^\/dev\/mapper\// ) {
exit_with("The device parameter $device is inaccurate. Only whole disks are allowed.", 14);
}
if (grep(/$device/, (@$dasd_ref, @$zfcp_ref))) {
my $zfcp = is_zfcp($device);
if (defined $zfcp and @ARGV > 1) {
exit_with("Multi-volume dumps aren't supported with zFCP.", 14);
}
push(@devices, (defined $zfcp) ? $zfcp : $device);
} else {
if (-b $device) {
exit_with("$device is in use or not a DASD/zFCP disk!", 14);
} else {
exit_with("$device does not exist!", 14);
}
}
}
if (@devices == 0) {
exit_with("No usable devices where provided.", 14);
}
return(@devices);
}
sub main
{
check_paths();
my @devices = analyze_cmd_parameters();
# only one dump device is possible with zFCP which is enforced in analyze_cmd_parameters
my $zfcp = is_zfcp($devices[0]);
if (defined $zfcp) {
setup_zfcpdump($zfcp);
} else {
setup_dasddump(@devices);
}
print("Creating the dump device was successful.\n");
}
main();

666
mkdump.pl.suse Normal file
View File

@ -0,0 +1,666 @@
#!/usr/bin/perl
########################################################################
#
# mkdump.pl - Preparing disks for use as S/390 dump device
#
# Copyright (c) 2011 Tim Hardeck, SUSE LINUX Products GmbH
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
# Based on mkdump.sh (c) 2004 Hannes Reinecke, SuSE AG
#
# License:
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
########################################################################
use strict;
use warnings;
use Fcntl;
use Getopt::Long;
my $VERSION = "2.0.4";
my $BLKID = "/sbin/blkid";
my $PARTED = "/usr/sbin/parted";
my $FDASD = "/sbin/fdasd";
my $DASDVIEW = "/sbin/dasdview";
my $DASDFMT = "/sbin/dasdfmt";
my $ZIPL = "/sbin/zipl";
my $UDEVADM = "/sbin/udevadm";
my $ZGETDUMP = "/sbin/zgetdump";
# temporary DASD device configuration file for Zipl
my $MDPATH = "/tmp/mvdump.conf.".`mcookie`;
chomp($MDPATH);
my $OPT_DEBUG = 0;
my $OPT_FORCE = 0;
my $OPT_VERBOSE = 0;
sub cleanup
{
# DASD
if (-e $MDPATH) {
system("rm -f $MDPATH");
}
}
sub exit_with
{
my $message = shift();
my $exitcode = shift();
print STDERR "$message Exiting...\n";
cleanup();
# fdasd isn't able to create volume label interactively
# could be fixed with a reformat
if ($exitcode == 65280) {
$exitcode = 12;
}
# bigger exit codes are not supported
if ($exitcode > 255) {
$exitcode = 255;
}
exit($exitcode);
}
sub run_cmd
{
my $cmd = shift();
my $output = "";
if (! $OPT_DEBUG) {
my ($app) = $cmd =~ /\/(\w+) /;
# run command
$output = `$cmd`;
my $exit_code = $?;
# wait for udev to finish processing
system("$UDEVADM settle");
# only print output in case of an error or in verbose mode
if ($output and ($exit_code != 0 or $OPT_VERBOSE)) {
print("$output\n");
}
if ($exit_code != 0) {
exit_with("$app failed with exit code $exit_code", $exit_code);
}
} else {
# only print the command in debug mode
print("\`$cmd\`\n");
}
return($output);
}
sub check_paths
{
for my $path ($BLKID, $PARTED, $FDASD, $DASDVIEW, $DASDFMT, $ZIPL, $UDEVADM, $ZGETDUMP) {
unless ( -x $path) {
exit_with("Command $path is not available.", 13);
}
}
}
sub read_file
{
my $path = shift();
open(my $file, "<", "$path") or exit_with("Unable to access $path: $!.", 15);
my @content = <$file>;
close($file);
# no need for arrays in case of single lines
if (@content > 1) {
return @content;
} else {
chomp($content[0]);
return($content[0]);
}
}
sub is_dasd
{
# remove leading /dev/
my $device = substr(shift(), 5);
if (-r "/sys/block/$device/device/discipline") {
return(1);
} else {
return(0);
}
}
sub has_free_single_kpartx
{
my $device = substr(shift(), 5);
return(0) unless ($device =~ /^dm-[0-9]+$/);
my $blockpath = "/sys/block/$device";
my @holders = glob("$blockpath/holders/*");
return(0) unless (@holders == 1);
my $dmuuid = read_file("$holders[0]/dm/uuid");
return(0) unless ($dmuuid =~ /^part1-mpath-/);
my @holderparts = split(/\//, $holders[0]);
my $holder = "/dev/" . $holderparts[-1];
if(-b $holder and sysopen(my $blockdev, $holder, O_RDWR|O_EXCL)) {
close($blockdev);
return(1);
}
return(0);
}
sub is_zfcp
{
# remove leading /dev/
my $device = substr(shift(), 5);
my $blockpath = "/sys/block/$device";
my $dmname = undef;
# if user passed a device name on cmdline that we listed before
# convert to a dm-[0-9]+ kernel device name
if ($device =~ /^mapper\//) {
$device = substr(readlink("/dev/" . $device), 3);
$blockpath = "/sys/block/" . $device;
}
# check if dm-multipath and get one path member
if ($device =~ /^dm-[0-9]+$/) {
my $dmuuid = read_file("$blockpath/dm/uuid");
return(undef) unless $dmuuid =~ /^mpath-/;
$dmname = read_file("$blockpath/dm/name");
opendir(DIR, "$blockpath/slaves/") or return(undef);
while (defined(my $pathmember = readdir(DIR))) {
# skip ".", "..", or other non scsi disk entries
next unless $pathmember =~ /^sd[a-z]+$/;
$device = $pathmember;
last;
}
closedir(DIR);
}
my $devpath = "/sys/block/$device/device";
unless (-r "$devpath/hba_id" or -r "$devpath/type") {
return(undef);
}
my $devtype = read_file("$devpath/type");
# SCSI type '0' means disk
if ($devtype == 0) {
if (defined $dmname) {
return("/dev/mapper/$dmname");
} else {
return("/dev/$device");
}
} else {
return(undef);
}
}
sub get_partition_num
{
# remove leading /dev/
my $device = substr(shift, 5);
my $part_num = grep(/\s+$device\d+/, read_file("/proc/partitions"));
return($part_num);
}
sub print_device
{
my $device = shift();
my $only_dump_disks = shift();
my $devpath;
if ($device =~ /^\/dev\/mapper\//) {
$devpath = "/sys/block/" . substr(readlink($device), 3);
} else {
$devpath = "/sys/block/" . substr($device, 5);
}
my $output = $device;
my $dump_device = 0;
my $size = int(read_file("$devpath/size") / 2048); # 512 Byte blocks
# size can't be read this way in case of unformatted devices
if ($size != 0) {
$output .= "\t${size}MB";
} else {
$output .= "\tunknown";
}
if (is_dasd($device)) {
my ($busid) = readlink("$devpath/device") =~ /(\w\.\w\.\w{4})/;
$output .= "\t$busid";
# check for dump record and list multi volumes
my $zgetdump_output = `$ZGETDUMP -d $device 2>&1`;
my @dump_devs = $zgetdump_output =~ /(\w\.\w\.\w{4})/g;
if (@dump_devs) {
$dump_device = 1;
$output .= "\tdumpdevice";
# no need to output the dump ids for a single device
if (@dump_devs > 1) {
for my $id (@dump_devs) {
$output .= "|$id";
}
}
} else {
# check for single volume dump devices
if ($zgetdump_output =~ /Single-volume DASD dump tool/) {
$dump_device = 1;
$output .= "\tdumpdevice";
}
}
} else {
# get one path member to fill path info for "yast onpanic"
if ($device =~ /^\/dev\/mapper\//) {
my $blockdev = substr(readlink($device), 3);
my $blockpath = "/sys/block/" . $blockdev;
opendir(DIR, "$blockpath/slaves/") or return(undef);
while (defined(my $pathmember = readdir(DIR))) {
# skip ".", "..", or other non scsi disk entries
next unless $pathmember =~ /^sd[a-z]+$/;
$devpath = "/sys/block/" . $pathmember;
last;
}
closedir(DIR);
}
my $adapter = read_file("$devpath/device/hba_id");
my $wwpn = read_file("$devpath/device/wwpn");
my $lun = read_file("$devpath/device/fcp_lun");
$output .= "\t$adapter\t$wwpn\t$lun";
# check for dump record
my $zgetdump = `$ZGETDUMP -d $device 2>&1`;
if ($? == 0) {
my ($dsize) = ($zgetdump =~ /Maximum dump size\.:\s+([0-9]+) MB/m);
$dsize = $size unless (defined($dsize));
$output = "$device\t${dsize}MB\t$adapter\t$wwpn\t$lun\tdumpdevice";
$dump_device = 1;
}
}
if ($only_dump_disks) {
if ($dump_device) {
print("$output\n");
}
} else {
print("$output\n");
}
}
sub list_free_disks
{
my $devices_ref = shift();
my $type = shift();
if (@$devices_ref) {
for my $device (@$devices_ref) {
print_device($device);
}
} else {
print STDERR "No free $type devices available!\n";
}
}
sub list_dump_disks
{
my @devices = @_;
if (@devices) {
for my $device (@devices) {
print_device($device, 1);
}
} else {
print STDERR "No dump devices available!\n";
}
}
sub determine_free_disks
{
my @dasd;
my @zfcp;
my @devices;
# gather block devices
my $path="/sys/block/";
opendir(DIR, $path) or exit_with("Unable to find $path: $!", 15);
while (defined(my $file = readdir(DIR))) {
# no need to add other devices then dasd* or sd*
# or dm-multipath
if ($file =~ /^dasd[a-z]+$/ or $file =~ /^sd[a-z]+$/ or
$file =~ /^dm-[0-9]+$/) {
push(@devices, $file);
}
}
closedir(DIR);
for my $entry (@devices) {
# only allow disks, no partitions
my ($device) = $entry =~ /^([a-z]+)$/;
# dm devices other than dm-multipath are filtered by is_zfcp()
($device) = $entry =~ /^(dm-[0-9]+)$/ unless ($device);
next unless ($device);
$device = "/dev/$device";
# determine if the block device could be accessed exclusively
if(-b $device and sysopen(my $blockdev, $device, O_RDWR|O_EXCL)) {
close($blockdev);
if (is_dasd($device)) {
push(@dasd, $device);
}
my $zfcp = is_zfcp($device);
if (defined $zfcp) {
push(@zfcp, $zfcp);
}
} else {
# A dm-multipath device with a single holder
# being a kpartx partition number 1 could still
# be free or contain a zfcpdump boot record.
# Due to the kpartx linear dm mapping, such
# dm-multipath device cannot open exclusively.
if (has_free_single_kpartx($device)) {
my $zfcp = is_zfcp($device);
if (defined $zfcp) {
push(@zfcp, $zfcp);
}
}
}
# wait for udev to process all events triggered by sysopen(,O_EXCL)
system("$UDEVADM settle");
}
return(\@dasd, \@zfcp);
}
sub prepare_dasd
{
my @devices = @_;
my $format_disks = "";
# check formatting
for my $device (@devices) {
# determine disk layout
my ($fmtstr) = `$DASDVIEW -x $device` =~ /(\w\w\w) formatted/;
SWITCH:
for($fmtstr) {
if (/NOT/) {
print("Unformatted disk, formatting $device.\n");
$format_disks .= " $device";
last SWITCH;
}
if (/LDL/) {
if ($OPT_FORCE) {
print("Linux disk layout, reformatting $device.\n");
$format_disks .= " $device";
} else {
print("$device was formatted with the Linux disk layout.\n");
print("Unable to use it without reformatting.\n");
exit_with("Re-issue the mkdump command with the --force option.", 12);
}
last SWITCH;
}
if (/CDL/) {
# allow reformatting with force, since fdasd isn't able to create volume label interactively
if ($OPT_FORCE) {
print("Compatible disk layout, force reformatting $device.\n");
$format_disks .= " $device";
} else {
print("$device: Compatible disk layout, Ok to use.\n");
}
last SWITCH;
}
exit_with("Unknown layout ($fmtstr), cannot use disk.", 11);
}
}
# format devices
if ($format_disks) {
#up to eight devices in parallel
run_cmd("$DASDFMT -P 8 -b 4096 -y -f $format_disks");
}
# check partitioning and partition
for my $device (@devices) {
my $part_num = get_partition_num($device);
if ($part_num == 0 or $OPT_FORCE) {
print("Re-partitioning disk $device.\n");
run_cmd("$FDASD -a $device");
} else {
# allow disk with one partition if it don't consist a file system
if ($part_num == 1) {
my ($fstype) = `$BLKID ${device}1` =~ /TYPE=\"(\w+)\"/;
if ($fstype) {
exit_with("Device ${device}1 already contains a filesystem of type $fstype.", 12);
}
} else {
exit_with("$part_num partitions detected, cannot use disk $device.", 12);
}
}
}
}
sub setup_dasddump
{
my @devices = @_;
prepare_dasd(@devices);
# create zipl device configuration file
# don't create files in debug mode
unless ($OPT_DEBUG) {
open(my $file, ">", $MDPATH) or exit_with("Unable to access $MDPATH: $!.", 15);
for my $device (@devices) {
print{$file}("${device}1\n");
}
close($file);
}
print("Creating dump record.\n");
run_cmd("${ZIPL} -V -n -M $MDPATH");
cleanup();
}
sub setup_zfcpdump
{
my $device = shift();
# check partitioning
my $part_num = get_partition_num($device);
if ($part_num == 0 or $OPT_FORCE) {
print("Re-partitioning disk $device.\n");
run_cmd("$PARTED -s -- $device mklabel gpt mkpart primary 0 -1");
} else {
if ($part_num > 1) {
exit_with("$part_num partitions detected, cannot use disk $device.", 12);
}
}
# install bootloader
print("Creating dump record.\n");
my $partdev;
if ($device =~ /^\/dev\/mapper\//) {
$partdev = $device . "-part1"; # kpartx partition on multipath
} else {
$partdev = $device . "1"; # real partition, single path SCSI
}
run_cmd("${ZIPL} -V -d ${partdev}");
cleanup();
}
sub print_version
{
print << "EOF";
mkdump $VERSION
Copyright (c) 2011 SUSE LINUX Products GmbH
License GPLv2 or (at your option) any later version.
<http://www.gnu.org/licenses/gpl-2.0.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Tim Hardeck <thardeck\@suse.de>.
EOF
exit(0);
}
sub print_usage
{
my $exitcode = shift();
print << "EOF";
Usage: mkdump [OPTIONS] [DEVICE]...
mkdump $VERSION
Prepare one or more volumes for use as S/390 dump device. Supported devices
are ECKD DASD and SCSI over zFCP disks, while multi-volumes are limited to DASD.
Only whole disks can be used, no partitions! If the device is incompatible
formatted/partioned, the script will refuse to install the dump record
unless the --force switch is given.
Disks which are in use or have mounted partitions will not be listed and can't be used.
The mentioning of "dumpdevice" after a disk indicates that it is an already usable dump device. Additionally multi-volume dump devices are indicated by the list of including DASD ids.
Options:
-h, --help display this help and exit
-V, --version display version information and exit
-d, --debug debug mode, do not run programs which commit changes
-v, --verbose be verbose and show command outputs
-f, --force force overwrite of the disk
-l, --list-dump display dump disks
-D, --list-dasd display usable DASD disks (Device, Size, ID, Dump)
-Z, --list-zfcp display usable SCSI over zFCP disks (Device, Size, ID, WWPN, LUN, Dump)
Report bugs on https://bugzilla.novell.com/
EOF
exit($exitcode);
}
sub analyze_cmd_parameters
{
#verbose, debug and force are global
my $opt_help = 0;
my $opt_version = 0;
my $opt_dump = 0;
my $opt_dasd = 0;
my $opt_zfcp = 0;
if (@ARGV == 0) {
print_usage(14);
}
Getopt::Long::Configure('bundling');
GetOptions(
'h|help' => \$opt_help,
'V|version' => \$opt_version,
'd|debug' => \$OPT_DEBUG,
'v|verbose' => \$OPT_VERBOSE,
'f|force' => \$OPT_FORCE,
'l|list-dump' => \$opt_dump,
'D|list-dasd' => \$opt_dasd,
'Z|list-zfcp' => \$opt_zfcp,
) or print_usage(14);
if ($opt_help) {
print_usage(0);
}
if ($opt_version) {
print_version();
}
# determine free dasd and zfcp devices
my ($dasd_ref, $zfcp_ref) = determine_free_disks();
if ($opt_dump) {
list_dump_disks(@$dasd_ref, @$zfcp_ref);
exit 0;
}
if ($opt_dasd) {
list_free_disks(\@$dasd_ref, "dasd");
}
if ($opt_zfcp) {
list_free_disks(\@$zfcp_ref, "zfcp");
}
# allow listing of both device types at the same time
if ($opt_dasd or $opt_zfcp) {
exit 0;
}
# check provided devices and be strict
my @devices;
for my $device (@ARGV) {
if (grep(/$device/, @devices)) {
exit_with("$device is mentioned more than once.", 14);
}
# dm devices other than dm-multipath are filtered by is_zfcp()
if ( $device =~ /^\/dev\/[a-z]+$/ == 0 and
$device !~ /^\/dev\/mapper\// ) {
exit_with("The device parameter $device is inaccurate. Only whole disks are allowed.", 14);
}
if (grep(/$device/, (@$dasd_ref, @$zfcp_ref))) {
my $zfcp = is_zfcp($device);
if (defined $zfcp and @ARGV > 1) {
exit_with("Multi-volume dumps aren't supported with zFCP.", 14);
}
push(@devices, (defined $zfcp) ? $zfcp : $device);
} else {
if (-b $device) {
exit_with("$device is in use or not a DASD/zFCP disk!", 14);
} else {
exit_with("$device does not exist!", 14);
}
}
}
if (@devices == 0) {
exit_with("No usable devices where provided.", 14);
}
return(@devices);
}
sub main
{
check_paths();
my @devices = analyze_cmd_parameters();
# only one dump device is possible with zFCP which is enforced in analyze_cmd_parameters
my $zfcp = is_zfcp($devices[0]);
if (defined $zfcp) {
setup_zfcpdump($zfcp);
} else {
setup_dasddump(@devices);
}
print("Creating the dump device was successful.\n");
}
main();

7
pkey.conf Normal file
View File

@ -0,0 +1,7 @@
#
# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
# All rights reserved.
#
# load pkey module at boot time
pkey

159
qeth_configure Normal file
View File

@ -0,0 +1,159 @@
#! /bin/sh
#
# qeth_configure
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Configures a qeth device by calling the IBM-provided chzdev command.
# Whereas this script used to validate the parameters provided to it,
# we now rely on chzdev to do that instead. The script is intended only
# as a "translation layer" to provide backward compatability for older
# scripts and tools that invoke it.
#
# Usage:
# qeth_configure [-i] [-l] [-f -t <CARDTYPE> ] [-o "Values"] -n <portno> -p <portname> <read chan> <write chan> <data chan> <online>
#
# -i Configure IP takeover
# -l Configure Layer2 support
# -f Override safety checks
# -t Valid cardtypes are: qeth, hsi - Deprecated
# -o General QETH options, separated by spaces
# -n QETH port number to use, 0 or 1. Only needed for real, not virtual
# devices.
# -p QETH Portname to use - Deprecated. OSAs no longer need a port name.
# read/write/data chan = x.y.ssss where
# x is always 0 until IBM creates something that
# uses that number
# y is the logical channel subsystem (lcss)
# number. Most often this is 0, but it could
# be non-zero
# ssss is the four digit subchannel address of
# the device, in hexidecimal, with leading
# zeros.
# online = 0 to take the device offline
# 1 to bring the device online
#
# Return values:
# Return codes are determined by the chzdev command.
#
mesg () {
echo "$@"
}
debug_mesg () {
case "${DEBUG}" in
yes) mesg "$@" ;;
*) ;;
esac
}
usage(){
echo "Usage: ${0} [options] <read chan> <write chan> <data chan> <online>"
echo " -i Configure IP takeover"
echo " -l Configure Layer2 support"
echo " -f Override safety checks"
echo " -t Valid cardtypes are: qeth, hsi - Deprecated."
echo " -o General QETH options, separated by spaces"
echo " -n QETH port number to use, 0 or 1. Only needed for real, not virtual"
echo " devices."
echo " -p QETH Portname to use - Deprecated. OSAs no longer need a port name."
echo " read/write/data chan = x.y.ssss where"
echo " x is always 0 until IBM creates something that"
echo " uses that number"
echo " y is the logical channel subsystem (lcss)"
echo " number. Most often this is 0, but it could"
echo " be non-zero"
echo " ssss is the four digit subchannel address of"
echo " the device, in hexidecimal, with leading"
echo " zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
}
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATE=$(date)
############################################################
# Parse the parameters from the command line
#
ARGS=$(getopt --options ifln:o:p:t: -n "qeth_configure" -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
eval set -- "${ARGS}"
debug_mesg "All the parms passed were ${ARGS}"
# Set some defaults
LAYER_MODE="layer2=0"
while true; do
case "${1}" in
-i) debug_mesg "Configure IP takeover"
PARM_LIST="${PARM_LIST} ipa_takeover/enable=1"
shift 1
;;
-f) debug_mesg "This used to mean udev rules will always be generated."
debug_mesg "For chzdev, it means safety checks will be overridden."
debug_mesg "Kinda sorta the same thing, really."
PARM_LIST="${PARM_LIST} -f"
shift 1
;;
-l) debug_mesg "Configure Layer 2 support"
LAYER_MODE="layer2=1"
shift 1
;;
-n) debug_mesg "Set QETH port number to ${2}"
PARM_LIST="${PARM_LIST} portno=${2}"
shift 2
;;
-o) debug_mesg "Add the following arbitrary parms: ${2}"
PARM_LIST="${PARM_LIST} ${2}"
shift 2
;;
-p) debug_mesg "QETH Port name is no longer used, don't specify it: ${2}"
shift 2
;;
-t) debug_mesg "This used to set the card type to ${2}"
debug_mesg "Now it gets ignored."
shift 2
;;
--) debug_mesg "Found the end of parms indicator: --"
shift 1
break
;;
*) debug_mesg "At the catch-all select entry"
debug_mesg "What was selected was ${1}"
shift 1
;;
esac
done
QETH_READ_CHAN=${1}
QETH_WRITE_CHAN=${2}
QETH_DATA_CHAN=${3}
ON_OFF=${4}
if [ -z "${QETH_READ_CHAN}" ] || [ -z "${QETH_WRITE_CHAN}" ] || [ -z "${QETH_DATA_CHAN}" ] || [ -z "${ON_OFF}" ]; then
mesg "You didn't specify all the needed parameters."
usage
exit 1
fi
if [ "${ON_OFF}" == 0 ]; then
debug_mesg "chzdev -d qeth --no-root-update ${QETH_READ_CHAN}"
chzdev -d qeth --no-root-update ${QETH_READ_CHAN}
elif [ "${ON_OFF}" == 1 ]; then
debug_mesg "chzdev -e qeth --no-root-update ${LAYER_MODE} ${PARM_LIST} ${QETH_READ_CHAN}"
chzdev -e qeth ${LAYER_MODE} --no-root-update ${PARM_LIST} ${QETH_READ_CHAN}
else mesg "You must specify a 0 or a 1 for the online/offline attribute."
usage
exit 1
fi
RC=${?}
if [ ${RC} -ne 0 ]; then
exit ${RC}
fi

66
qeth_configure.8 Normal file
View File

@ -0,0 +1,66 @@
.TH qeth_configure "8" "July 2013" "s390-tools"
.SH NAME
qeth_configure \- Configures or deconfigures a HiperSocket adapter or an IBM Open Systems Adapter (OSA) in QDIO mode
.SH SYNOPSIS
.B qeth_configure [options] read_channel write_channel data_channel online
.SH DESCRIPTION
.B qeth_configure
is intended to make it easy to persistently add and remove HiperSocket Adapters and Open System Adapters (OSAs) that are in QDIO mode. In addition to bringing the adapter online or offline, it will also create or delete the necessary udev rules for the adapter.
.SH PARAMETERS
.IP read_channel
The device number of the read channel of the adapter. Takes the form x.y.ssss.
.IP write_channel
The device number of the write channel of the adapter.Takes the form x.y.ssss.
.IP data_channel
The device number of the data channel of the adapter.Takes the form x.y.ssss.
.RS
where
.RS
.B x
is always 0 until IBM creates something that uses that number.
.RE
.RS
.B y
is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero.
.RE
.RS
.B ssss
is the four digit subchannel address of the device, in hexidecimal, with leading zeros. If entered in upper/mixed case, this is automatically converted to lower case.
.RE
.RE
.RS
.RE
.RE
.IP online
Either a literal 1 to bring the adapter online or a literal 0 to take it offline
.SH OPTIONAL PARAMETERS
.IP -i
Configure IP takeover
.IP -l
Configure Layer 2 support
.IP -f
Force creation of udev rules, do not check values in /sys. Requires -t to be specfied.
.IP "-t CARDTYPE"
The type of card being configured. Valid values are: qeth, hsi, or osn.
.IP "-o ""Values"""
General/arbitrary QETH options, separated by spaces
.IP "-n portnumber"
QETH port number to use, 0 or 1. Only needed for real, not virtual devices.
.IP "-p portname"
QETH Portname to use. Only needed if sharing a real OSA with z/OS.
.SH FILES
Please see the documentation of
.B chzdev.
.SH ENVIRONMENT
.IP DEBUG
If set to "yes" some minimal debugging information is output during execution.
.SH DIAGNOSTICS
Messages and return codes are determined by the
.B chzdev
command.
If environment variable DEBUG is set to "yes," it shows the command line of the invoked
.B chzdev,
and a message for each command line option is issued on stdout.
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

50
read_values.8 Normal file
View File

@ -0,0 +1,50 @@
.TH read_values "8" "March 2015" "s390-tools"
.SH NAME
read_values \- Read information from the /sys and /proc filesystems for SUSE Customer Center (SCC) and the like.
.SH SYNOPSIS
.B read_values [-s] [-u] [-c] [-a Attribute] [-L Keyword] [-d debug] [-h]
.SH DESCRIPTION
.B read_values
is intended to make it easy to read values from the /sys and /proc filesystems. Those values may be at different places depending on the machine type and the kernel version.
.SH PARAMETERS
.IP -s
Outputs the values needed by the SCC (SUSE Customer Center)
.IP -u
Creates a uuid for this system
.IP -c
Prints the CPU type of the current system
.IP -a Attribute
Prints the value of the
.B Attribute
.IP -L Keyword
The
.B Keyword
may be
.B Attribute
or
.B Recognised.
With this option you get a list of all
.B Attributes
the programm can accept (
.B Attribute
) or a list of attributes which in turn can be used for the option -L (
.B Recognised
).
.SH FILES
.I /sys and /proc
.SH DIAGNOSTICS
The following messages may be issued on stderr:
.IP
.B Unable to open /proc/sysinfo
or
.B Unable to open sysinfo.zvm
.RS
The named file cannot be opened. This means the tool can't do anything useful. Return code 99 is set.
.RE
.IP
.B Only one of the options a, c, L, s or u can be specified.
.RS
Only one of the options a, c, L, s or u can be specified at a time. Return code 1 is set.
.RE
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

628
read_values.c Normal file
View File

@ -0,0 +1,628 @@
/********************************************************************************/
/* */
/* Copyright (C) 2014-2015, 2019-2023 SUSE LLC */
/* */
/* All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#include <sys/utsname.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <query_capacity.h>
/*
* Data types
*/
enum datatypes {
integer,
string,
floatingpoint
};
#define WITHOUT_KEY 0
#define WITH_KEY 1
static char *versionstring = "Version 1.0.5 2024-06-20 14:30";
static char *version = "1.0.5";
void *configuration_handle = NULL;
int layers = -1;
/*
* List of machine types
*/
struct machinetype {
enum qc_model_families model_families;
char *typenumber;
char *fullname;
} machinetypes[] = {
{ QC_TYPE_FAMILY_IBMZ, "2064", "2064 = z900 IBM eServer zSeries 900" },
{ QC_TYPE_FAMILY_IBMZ, "2066", "2066 = z800 IBM eServer zSeries 800" },
{ QC_TYPE_FAMILY_IBMZ, "2084", "2084 = z990 IBM eServer zSeries 990" },
{ QC_TYPE_FAMILY_IBMZ, "2086", "2086 = z890 IBM eServer zSeries 890" },
{ QC_TYPE_FAMILY_IBMZ, "2094", "2094 = z9-EC IBM System z9 Enterprise Class" },
{ QC_TYPE_FAMILY_IBMZ, "2096", "2096 = z9-BC IBM System z9 Business Class" },
{ QC_TYPE_FAMILY_IBMZ, "2097", "2097 = z10-EC IBM System z10 Enterprise Class" },
{ QC_TYPE_FAMILY_IBMZ, "2098", "2098 = z10-BC IBM System z10 Business Class" },
{ QC_TYPE_FAMILY_IBMZ, "2817", "2817 = z196 IBM zEnterprise 196" },
{ QC_TYPE_FAMILY_IBMZ, "2818", "2818 = z114 IBM zEnterprise 114" },
{ QC_TYPE_FAMILY_IBMZ, "2827", "2827 = z12-EC IBM zEnterprise EC12" },
{ QC_TYPE_FAMILY_IBMZ, "2828", "2828 = z12-BC IBM zEnterprise BC12" },
{ QC_TYPE_FAMILY_IBMZ, "2964", "2964 = z13 IBM z13" },
{ QC_TYPE_FAMILY_LINUXONE, "2964", "2964 = IBM LinuxONE Emperor" },
{ QC_TYPE_FAMILY_IBMZ, "2965", "2965 = z13s IBM z13s (single frame)" },
{ QC_TYPE_FAMILY_LINUXONE, "2965", "2965 = IBM LinuxONE Rockhopper" },
{ QC_TYPE_FAMILY_IBMZ, "3906", "3906 = z14 IBM z14" },
{ QC_TYPE_FAMILY_LINUXONE, "3906", "3906 = IBM LinuxONE Emperor II" },
{ QC_TYPE_FAMILY_IBMZ, "3907", "3907 = z14 ZR1 IBM z14 ZR1" },
{ QC_TYPE_FAMILY_LINUXONE, "3907", "3907 = IBM LinuxONE Rockhopper II" },
{ QC_TYPE_FAMILY_IBMZ, "8561", "8561 = z15 T01 IBM z15 T01" },
{ QC_TYPE_FAMILY_LINUXONE, "8561", "8561 = IBM LinuxONE III LT1" },
{ QC_TYPE_FAMILY_IBMZ, "8562", "8562 = z15 T02 IBM z15 T02" },
{ QC_TYPE_FAMILY_LINUXONE, "8562", "8562 = IBM LinuxONE III LT2" },
{ QC_TYPE_FAMILY_IBMZ, "3931", "3931 = z16 A01 IBM z16 A01" },
{ QC_TYPE_FAMILY_LINUXONE, "3931", "3931 = IBM LinuxONE Emperor 4" },
{ QC_TYPE_FAMILY_IBMZ, "3932", "3932 = z16 A02 IBM z16 A02" },
{ QC_TYPE_FAMILY_LINUXONE, "3932", "3932 = IBM LinuxONE Rockhopper 4" },
};
int debug = 0;
/******************************************************************************/
/* */
/* Print the program version */
/* */
/******************************************************************************/
void print_version()
{
printf("Version: %s\n", version);
}
/******************************************************************************/
/* */
/* Look for one attribute and print it */
/* */
/******************************************************************************/
void print_attribute(char *user_string, int level, enum qc_attr_id attribute, enum datatypes type, int print_key)
{
int erg = 0;
const char *result_string = NULL;
int result_int = 0;
float result_float = 0.0;
switch (type)
{
case integer:
erg = qc_get_attribute_int(configuration_handle, attribute, level, &result_int);
break;
case string:
erg = qc_get_attribute_string(configuration_handle, attribute, level, &result_string);
break;
case floatingpoint:
erg = qc_get_attribute_float(configuration_handle, attribute, level, &result_float);
break;
default:
break;
}
if (erg == 1) {
if (print_key == WITH_KEY) {
printf("%s : ",(user_string == NULL? "NULL": user_string));
} /* endif */
switch (type)
{
case integer:
printf("%d\n",result_int);
break;
case string:
printf("%s\n", result_string);
break;
case floatingpoint:
printf("%f\n",result_float);
break;
default:
break;
}
} /* endif */
else {
if ( erg == 0 ) {
/* printf("%s : Attribute exists, but is not set. \n", (user_string == NULL? "NULL": user_string)); */
} /* endif */
else if ( erg < 0) {
printf("%s: An error occurred retrieving the attribute. Error: erg = %d, result_string = %s \n", user_string, erg, (result_string == NULL? "NULL": result_string));
} /* end else if */
/* */
/* TODO qc_get_attribute_string returned error */
/* */
}
} /* print_attribute */
/********************************************************************************/
/* */
/* Open the lib and get the handle */
/* */
/********************************************************************************/
int read_sysinfo()
{
int return_code;
configuration_handle = qc_open(&return_code);
if (return_code < 0) {
printf("Error: Unable to open configuration, return_code =%d\n", return_code);
return -1;
} /* endif */
if (return_code > 0) {
printf("Warning: Unable to read configuration completely, return_code =%d\n", return_code);
return -2;
} /* endif */
if (configuration_handle == NULL) {
printf("Error: Unable to open configuration, return_code =%d\n", return_code);
return -3;
} /* endif */
layers = qc_get_num_layers(configuration_handle, &return_code);
if (layers < 0) {
printf("Error: Unable to retrieve number of layers, return_code =%d\n", return_code);
return -4;
} /* endif */
return 0;
} /* read_sysinfo */
/********************************************************************************/
/* */
/* Look at the type of machine we're running on and print out a user */
/* friendly string */
/* */
/********************************************************************************/
void print_cputype()
{
int i, search;
int erg;
const char *cpu_type = NULL;
int family_type = -1;
/*
* First find out whether we run on an IBM Z, or a LinuxONE system
*/
erg = qc_get_attribute_int(configuration_handle, qc_type_family, 0, &family_type);
if (erg <= 0 || family_type == -1) {
printf("Error reading family type\n");
return;
} /* endif */
/*
* Now get the machine ID
*/
erg = qc_get_attribute_string(configuration_handle, qc_type, 0, &cpu_type);
if (erg == 1 && cpu_type != NULL) {
for (i = 0, search = 1; (i < sizeof(machinetypes) / sizeof(struct machinetype)) && search ; i++)
{
if ((family_type == machinetypes[i].model_families) && (strcmp(cpu_type, machinetypes[i].typenumber) == 0)) {
printf("%s\n", machinetypes[i].fullname);
search = 0;
} /* endif */
} /* endfor */
if (search != 0) {
printf("An unknown machine type was reported: %s\n\
Please file a bug report with this output:\n" , cpu_type);
/* TODO output of /proc/sysinfo */
} /* endif */
} /* endif */
return;
} /* print_cputype */
/********************************************************************************/
/* */
/* Print out the values for SCC */
/* */
/* To uniquely identify a machine the following information is used: */
/* */
/* Type */
/* Sequence code */
/* CPUs total */
/* CPUs IFL */
/* LPAR Number */
/* LPAR Characteristics: */
/* LPAR CPUs */
/* LPAR IFLs */
/* */
/* Optional: */
/* */
/* VM00 Name */
/* VM00 Control Programm */
/* VM00 CPUs */
/* */
/********************************************************************************/
void print_scc()
{
print_version();
print_attribute("Type", 0, qc_type, string, WITH_KEY);
print_attribute("Type Name", 0, qc_type_name, string, WITH_KEY);
print_attribute("Sequence Code", 0, qc_sequence_code, string, WITH_KEY);
print_attribute("CPUs Total", 0, qc_num_ifl_total, integer, WITH_KEY);
print_attribute("CPUs IFL", 0, qc_num_ifl_total, integer, WITH_KEY);
print_attribute("LPAR Number", 1, qc_partition_number, integer, WITH_KEY);
print_attribute("LPAR Name", 1, qc_layer_name, string, WITH_KEY);
print_attribute("LPAR Characteristics", 1, qc_partition_char, string, WITH_KEY);
print_attribute("LPAR CPUs Total", 1, qc_num_ifl_total, integer, WITH_KEY);
print_attribute("LPAR CPUs IFL", 1, qc_num_ifl_total, integer, WITH_KEY);
if (layers > 2) {
/*
* This means, that eather zKVM or z/Vm is running
*/
print_attribute("VM00 Name", 3, qc_layer_name, string, WITH_KEY);
print_attribute("VM00 Control Program", 2, qc_control_program_id, string, WITH_KEY);
print_attribute("VM00 CPUs Total", 3, qc_num_cpu_total, integer, WITH_KEY);
print_attribute("VM00 IFLs", 3, qc_num_cpu_total, integer, WITH_KEY);
} /* endif */
return;
} /* print_scc */
/******************************************************************************/
/* */
/* Secure boot support models ( check_model () ) */
/* Only the following machines support secure boot: */
/* z14, z14 ZR1, z15, z16 */
/* */
/******************************************************************************/
int check_model (const char *cpu) {
#define IBM_Models 6 /* Number of IBM models listed below */
char *types[IBM_Models] = {
"3906",
"3907",
"8561",
"8562",
"3931",
"3932",
};
int i;
int models = sizeof(types) / sizeof(types[0]);
for ( i = 0; i < models; i++) {
if ( !strcmp(cpu,types[i]) ) {
return 1;
};
}
return 0;
} /* check_model */
/******************************************************************************/
/* */
/* print out whether secure boot is enabled */
/* */
/******************************************************************************/
void print_secure_mode()
{
int erg;
int release_major;
int release_sub;
int release_minor;
const char *cpu_type = NULL;
int cpu_okay = 0;
int Layer = 0;
int i = 0;
/*
* First we have to check whether we have the appropriate kernel Level (>= 5.3)
*/
struct utsname uts;
erg = uname(&uts);
if (erg != 0) {
perror ("Error executing uname(): ");
return;
} /* endif */
#if 0
printf("sysname: %s\n", uts.sysname);
printf("nodename: %s\n", uts.nodename);
printf("release: %s\n", uts.release);
#endif
/*
* A release number looks like: m.s.mi
* where m, s, mi are numbers with one ore more digits
* Minimum kernel version is 5.3
*/
erg = sscanf(uts.release,"%d.%d.%d-%*s", &release_major, &release_sub, &release_minor);
if ( release_major < 5 ) {
goto return_does_not_exist;
}
if ( release_sub < 3 ) {
goto return_does_not_exist;
}
#if 0
printf("Translated successfully: %d\n", erg);
printf("release_major: %d\n", release_major);
printf("release_sub: %d\n", release_sub);
printf("release_minor: %d\n", release_minor);
printf("version: %s\n", uts.version);
printf("machine: %s\n", uts.machine);
printf("Print_secure called\n");
#endif
/*
* Only the following machines support secure boot:
* z14, z15, z16
* 3906, 3907, 8561, 8562, 3931, 3932
*/
erg = qc_get_attribute_string(configuration_handle, qc_type, 0, &cpu_type);
if (erg == 1 && cpu_type != NULL) {
cpu_okay = check_model(cpu_type);
if ( cpu_okay == 0 ) {
goto return_does_not_exist;
} /* endif */
} /* endif */
for ( i = 0; i < layers; i++) {
erg = qc_get_attribute_int(configuration_handle, qc_layer_type_num, i, &Layer);
if (erg == 1) {
print_attribute("Secure mode on ", i, qc_has_secure, integer, WITH_KEY);
print_attribute("Secure mode used", i, qc_secure, integer, WITH_KEY);
} /* endif */
} /* endfor */
return;
return_does_not_exist:
/*
* Software or hardware does not support secure boot.
*/
puts("Secure mode on : 0\nSecure mode used : 0");
return;
} /* print_secure_mode */
/******************************************************************************/
/* */
/* print out the uuid for this machine */
/* */
/******************************************************************************/
int print_uuid()
{
const char *result_string = NULL;
int erg;
erg = qc_get_attribute_string(configuration_handle, qc_sequence_code, 0, &result_string);
if (erg != 1)
{
puts("Error reading the Serial Number");
return 1;
}
printf("%s", result_string);
result_string = NULL;
erg = qc_get_attribute_string(configuration_handle, qc_layer_name, 1, &result_string);
if (erg != 1)
{
puts("Error reading the LPAR Name");
return 1;
}
printf("-%s", result_string);
result_string = NULL;
if (layers > 2) {
erg = qc_get_attribute_string(configuration_handle, qc_layer_name, 3, &result_string);
if (erg != 1)
{
puts("Error Reading the VM Name");
return 1;
}
printf("-%s", result_string);
}
putchar('\n');
return 0;
} /* print_uuid */
/******************************************************************************/
/* */
/* print out the list of valid / found symbols */
/* */
/******************************************************************************/
void list(char * list_attribute_param)
{
return;
} /* list */
/******************************************************************************/
/* */
/* print out the requested attribute */
/* */
/******************************************************************************/
void print_user_attribute(char *key, char *attribute_param, int layer)
{
return;
} /* print_user_attribute */
/******************************************************************************/
/* */
/* Help Function */
/* */
/******************************************************************************/
void help()
{
puts("help:\n\
\n\
-a <attribute> List the value of the named attribute\n\
-c Print the cputype of this machine\n\
-d <number> Debug Level\n\
-h this help\n\
-L <keyword> List the requested list (Attribute, Recognised)\n\
-s create Info for SCC\n\
-S report whether secure boot is switched on\n\
-u create uuid\n\
-V print version string\n\
");
#if 0
if (debug != 0) {
puts("\n\
Valid values for debug:\n\
4 - read sysinfo.zvm from current directory instead of /proc/sysinfo\n\
8 - printout lines read in from source (see debug == 4)\n\
16 - printf found keys in store_value\n\
32 - Search expression in show attribute\n\
");
} /* endif */
#endif
} /* help */
/******************************************************************************/
/* */
/* Main */
/* */
/******************************************************************************/
int main(int argc, char **argv, char **envp)
{
int opt;
int read_sysinfo_opt;
int print_attr;
int print_cpu;
int print_secure;
int print_help;
int list_attr;
int create_scc;
int create_uuid;
int erg;
int return_code;
char *print_attribute_param = NULL;
char *list_attribute_param = NULL;
void *configuration_handle_tmp = NULL;
read_sysinfo_opt =
print_attr =
print_cpu =
print_secure =
print_help =
list_attr =
create_scc =
create_uuid =
return_code =
erg = 0;
if (strcmp(argv[0],"cputype") == 0) {
read_sysinfo_opt++;
print_cpu++;
} /* endif */
else {
while ((opt = getopt(argc, argv, "a:cd:hL:sSuV")) != -1) {
switch (opt)
{
case 'a':
read_sysinfo_opt++;
print_attr++;
print_attribute_param = strdup(optarg);
break;
case 'c':
read_sysinfo_opt++;
print_cpu++;
break;
case 'd':
debug = atoi(optarg);
if ((debug & 1) == 1) {
setenv("QC_DEBUG", "1", 1);
} /* endif */
if ((debug & 2) == 2) {
setenv("QC_AUTODUMP", "1", 1);
} /* endif */
debug = debug >> 2;
break;
case 'L':
read_sysinfo_opt++;
list_attr++;
list_attribute_param = strdup(optarg);
break;
case 's': /* create unique string for scc */
read_sysinfo_opt++;
create_scc++;
break;
case 'S': /* print out whether secure boot is enabled */
read_sysinfo_opt++;
print_secure++;
break;
case 'u': /* create UUID */
read_sysinfo_opt++;
create_uuid++;
break;
case 'V':
printf("%s\n",versionstring);
return 0;
break;
case 'h':
default:
print_help++;
break;
} /* endswitch */
} /* while */
} /* endlse */
if (print_help != 0) {
help();
return 0;
} /* endif */
if (read_sysinfo_opt != 0) {
if ((erg = read_sysinfo()) != 0) {
return -erg;
} /* endif */
} /* endif */
if ((print_attr + print_cpu + print_secure + list_attr + create_scc + create_uuid) > 1) {
fputs("Only one of the options a, c, L, s, S or u can be specified.\n",stderr);
return 1;
} /* endif */
/* still not implemented thatfore set to zero */
list_attr = print_attr = 0;
if (print_attr != 0) {
print_user_attribute(NULL, print_attribute_param, layers);
goto main_exit;
} /* endif */
if (print_cpu != 0) {
print_cputype();
goto main_exit;
} /* endif */
if (print_secure != 0) {
print_secure_mode();
goto main_exit;
} /* endif */
if (list_attr != 0) {
list(list_attribute_param);
goto main_exit;
} /* endif */
if (create_scc != 0) {
print_scc();
goto main_exit;
} /* endif */
if (create_uuid != 0) {
if(print_uuid() == 1){
goto main_exit_error;
}
goto main_exit;
} /* endif */
help();
main_exit:
if (configuration_handle != NULL) {
configuration_handle_tmp = qc_open(&return_code);
qc_close(configuration_handle);
setenv("QC_DEBUG", "0", 1);
setenv("QC_AUTODUMP", "0", 1);
qc_close(configuration_handle_tmp);
} /* endif */
return 0;
main_exit_error:
return 1;
} /* end main */

2
rules.hw_random Normal file
View File

@ -0,0 +1,2 @@
# Rules to add hw_random node to maintain SLES11-SP1 backward compatibility
KERNEL=="hwrng", SYMLINK+="hw_random"

2
rules.xpram Normal file
View File

@ -0,0 +1,2 @@
# Rules to add xpram* nodes to maintain SLES11-SP1 backward compatibility
KERNEL=="sl*[0-9]", SYMLINK+="xpram%n"

View File

@ -0,0 +1,969 @@
From d6b702d5791b47f735960ad1f6986e0a32768df6 Mon Sep 17 00:00:00 2001
From: Eduard Shishkin <edward6@linux.ibm.com>
Date: Thu, 11 Jul 2024 10:43:37 +0200
Subject: [PATCH] zipl/src: add basic support for multiple target base disks
. Modify disk_get_info() to process multiple sets of target parameters
provided by the helper script and store it in the array of "targets"
of the structure job_target_data;
. Besides the logical device, maintain an array of physical base disks
in the disk_info structure;
. Use the logical target device only to create bootmap (it is
automatically mirrored by the respective linux driver (dm, or md)
managing the mirrored target). In contrast, install bootstrap blocks
to each physical base disk individually, bypassing that driver;
. Report in verbose mode on which base disks the bootstrap
installation was performed;
. Use the following logic of setting @info->device (which is printed
as "Device...:" in verbose mode):
. source_auto - the target base disk is set;
. source_script - the target (logical) device is set;
. source_user - the device specified by user (via --targetbase
option), or config file is set.
Signed-off-by: Eduard Shishkin <edward6@linux.ibm.com>
Reviewed-by: Stefan Haberland <sth@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
zipl/include/disk.h | 14 +-
zipl/include/install.h | 2
zipl/include/job.h | 122 ++++++++++++++++++--
zipl/include/zipl.h | 1
zipl/src/bootmap.c | 23 ++-
zipl/src/disk.c | 295 +++++++++++++++++++++++++++++++++++++------------
zipl/src/install.c | 89 +++++++++-----
zipl/src/job.c | 82 +++++++------
8 files changed, 469 insertions(+), 159 deletions(-)
--- a/zipl/include/disk.h
+++ b/zipl/include/disk.h
@@ -56,13 +56,14 @@
/* targetbase definition */
typedef enum {
defined_as_device,
- defined_as_name
+ defined_as_name,
+ undefined
} definition_t;
/* Disk information type */
struct disk_info {
disk_type_t type;
- dev_t device;
+ dev_t device; /* logical device for bootmap creation */
dev_t partition;
int devno;
int partnum;
@@ -72,8 +73,11 @@
struct hd_geometry geo;
char* name;
char* drv_name;
- definition_t targetbase;
+ definition_t targetbase_def;
int is_nvme;
+ dev_t basedisks[MAX_TARGETS]; /* array of physical disks for
+ * bootstrap blocks recording
+ */
};
struct file_range {
@@ -113,6 +117,9 @@
struct disk_info *info, int align,
off_t *offset);
void disk_print_devt(dev_t d);
+void disk_print_devname(dev_t d);
+void prepare_footnote_ptr(int source, char *ptr);
+void print_footnote_ref(int source, const char *prefix);
void disk_print_info(struct disk_info *info, int source);
int disk_is_zero_block(disk_blockptr_t* block, struct disk_info* info);
blocknum_t disk_compact_blocklist(disk_blockptr_t* list, blocknum_t count,
@@ -122,7 +129,6 @@
disk_blockptr_t** blocklist,
struct disk_info* pinfo);
int disk_check_subchannel_set(int devno, dev_t device, char* dev_name);
-void disk_print_geo(struct disk_info *data);
int fs_map(int fd, uint64_t offset, blocknum_t *mapped, int fs_block_size);
#endif /* not DISK_H */
--- a/zipl/include/install.h
+++ b/zipl/include/install.h
@@ -71,7 +71,7 @@
struct program_component *components[NR_PROGRAM_COMPONENTS];
int nr_menu_entries;
int fd;
- char *device;
+ char *basetmp[MAX_TARGETS];
char *filename;
unsigned int tmp_filename_created:1;
unsigned int skip_prepare:1;
--- a/zipl/include/job.h
+++ b/zipl/include/job.h
@@ -18,7 +18,6 @@
#include "disk.h"
#include "zipl.h"
-
enum job_id {
job_print_usage = 1,
job_print_version = 2,
@@ -30,6 +29,21 @@
job_mvdump = 8,
};
+/*
+ * Set of parameters per physical disk, which are provided
+ * either by user, or by helper script
+ */
+struct target {
+ char *targetbase;
+ disk_type_t targettype;
+ int targetcylinders;
+ int targetheads;
+ int targetsectors;
+ int targetblocksize;
+ blocknum_t targetoffset;
+ int check_params;
+};
+
/* target information source */
typedef enum {
source_unknown = 0,
@@ -39,17 +53,21 @@
} source_t;
struct job_target_data {
- char* bootmap_dir;
- char* targetbase;
- disk_type_t targettype;
- int targetcylinders;
- int targetheads;
- int targetsectors;
- int targetblocksize;
- blocknum_t targetoffset;
+ char *bootmap_dir;
+ int nr_targets;
+ struct target targets[MAX_TARGETS];
source_t source;
};
+enum target_params {
+ TARGET_BASE,
+ TARGET_TYPE,
+ TARGET_GEOMETRY,
+ TARGET_BLOCKSIZE,
+ TARGET_OFFSET,
+ LAST_TARGET_PARAM
+};
+
struct job_common_ipl_data {
char* image;
char* parmline;
@@ -142,12 +160,94 @@
int is_ldipl_dump;
};
+static inline struct target *target_at(struct job_target_data *data,
+ int index)
+{
+ return index >= MAX_TARGETS ? NULL : &data->targets[index];
+}
+
+static inline char *get_targetbase(struct job_target_data *data, int index)
+{
+ return target_at(data, index)->targetbase;
+}
+
+static inline void set_targetbase(struct job_target_data *data, int index,
+ char *value)
+{
+ target_at(data, index)->targetbase = value;
+}
+
+static inline disk_type_t get_targettype(struct job_target_data *data,
+ int index)
+{
+ return target_at(data, index)->targettype;
+}
+
+int set_targettype(struct job_target_data *data, int index, char *value);
+
+static inline char *job_get_targetbase(struct job_data *job)
+{
+ return get_targetbase(&job->target, 0);
+}
+
+static inline void job_set_targetbase(struct job_data *job, char *value)
+{
+ set_targetbase(&job->target, 0, value);
+}
+
+static inline int job_get_nr_targets(struct job_data *job)
+{
+ return job->target.nr_targets;
+}
+
+static inline void job_set_nr_targets(struct job_data *job, int value)
+{
+ job->target.nr_targets = value;
+}
+
+static inline disk_type_t job_get_targettype(struct job_data *job)
+{
+ return get_targettype(&job->target, 0);
+}
+
+int job_set_targettype(struct job_data *job, char *value);
+
+#define define_target_param_ops(_TYPE_, _PARAM_) \
+static inline _TYPE_ get_target##_PARAM_(struct job_target_data *data, \
+ int index) \
+{ \
+ return target_at(data, index)->target##_PARAM_; \
+} \
+ \
+static inline void set_target##_PARAM_(struct job_target_data *data, \
+ int index, _TYPE_ value) \
+{ \
+ target_at(data, index)->target##_PARAM_ = value; \
+} \
+ \
+static inline _TYPE_ job_get_target##_PARAM_(struct job_data *job) \
+{ \
+ return get_target##_PARAM_(&job->target, 0); \
+} \
+ \
+static inline void job_set_target##_PARAM_(struct job_data *job, \
+ _TYPE_ value) \
+{ \
+ set_target##_PARAM_(&job->target, 0, value); \
+}
+
+define_target_param_ops(int, cylinders)
+define_target_param_ops(int, heads)
+define_target_param_ops(int, sectors)
+define_target_param_ops(int, blocksize)
+define_target_param_ops(blocknum_t, offset)
+
/**
- * Return true, if target parameters for the base disk are set
+ * Return true, if target parameters are set at least for one target base disk
*/
static inline int target_parameters_are_set(struct job_target_data *td)
{
- return td->targetbase != NULL;
+ return get_targetbase(td, 0) != NULL;
}
int job_get(int argc, char* argv[], struct job_data** data);
--- a/zipl/include/zipl.h
+++ b/zipl/include/zipl.h
@@ -41,6 +41,7 @@
#define MENU_DEFAULT_TIMEOUT 0
#define MAX_DUMP_VOLUMES 32
+#define MAX_TARGETS 32
#define SECURE_BOOT_UNDEFINED -1
#define SECURE_BOOT_DISABLED 0
--- a/zipl/src/bootmap.c
+++ b/zipl/src/bootmap.c
@@ -1477,9 +1477,9 @@
printf("Target device information\n");
disk_print_info(bis->info, job->target.source);
}
- if (misc_temp_dev(bis->info->device, 1, &bis->device))
+ if (misc_temp_dev(bis->info->device, 1, &bis->basetmp[0]))
return -1;
- if (check_dump_device(job, bis->info, bis->device))
+ if (check_dump_device(job, bis->info, bis->basetmp[0]))
return -1;
printf("Building bootmap directly on partition '%s'%s\n",
bis->filename,
@@ -1543,6 +1543,8 @@
static int prepare_build_program_table_file(struct job_data *job,
struct install_set *bis)
{
+ int i;
+
if (bis->skip_prepare)
/* skip the preparation work */
return 0;
@@ -1576,8 +1578,12 @@
printf("Target device information\n");
disk_print_info(bis->info, job->target.source);
}
- if (misc_temp_dev(bis->info->device, 1, &bis->device))
- return -1;
+ for (i = 0; i < job_get_nr_targets(job); i++) {
+ if (misc_temp_dev(bis->info->basedisks[i],
+ 1,
+ &bis->basetmp[i]))
+ return -1;
+ }
/* Check configuration number limits */
if (job->id == job_menu) {
if (check_menu_positions(&job->data.menu, job->name,
@@ -1692,9 +1698,9 @@
/* Retrieve target device information */
if (disk_get_info(job->data.dump.device, &job->target, &info))
return -1;
- if (misc_temp_dev(info->device, 1, &bis->device))
+ if (misc_temp_dev(info->device, 1, &bis->basetmp[0]))
return -1;
- if (check_dump_device(job, info, bis->device))
+ if (check_dump_device(job, info, bis->basetmp[0]))
return -1;
assert(!job->target.bootmap_dir);
@@ -1844,6 +1850,9 @@
if (bis->tmp_filename_created)
misc_free_temp_file(bis->filename);
free(bis->filename);
- misc_free_temp_dev(bis->device);
+ for (i = 0; i < MAX_TARGETS; i++) {
+ if (bis->basetmp[i])
+ misc_free_temp_dev(bis->basetmp[i]);
+ }
disk_free_info(bis->info);
}
--- a/zipl/src/disk.c
+++ b/zipl/src/disk.c
@@ -187,43 +187,134 @@
return rc;
}
+/**
+ * Process a script output represented by FH and consisting
+ * of pairs 'key=value' (each such pair is on a separate line).
+ * Check its consistency and set the extracted target parameters
+ * to the array of "targets" at TD.
+ *
+ * NOTE: this function defines specifications on valid output of
+ * zipl helper scripts. See zipl-support-for-mirrored-devices.txt
+ * for details. Before modifying this function, make sure that it
+ * won't lead to format change.
+ */
static int set_target_parameters(FILE *fh, struct job_target_data *td)
{
- int checkparm = 0;
+ int idx[LAST_TARGET_PARAM] = {0};
+ struct target *t;
char buffer[80];
char value[40];
+ char *error;
+ int i;
+ /**
+ * Process a stream of 'key=value' pairs and distribute
+ * them into groups.
+ * The i-th occurrence of some "key" in the stream means
+ * that the respective pair belongs to the group #i
+ */
+ error = "Exceeded the maximum number of base disks";
while (fgets(buffer, 80, fh)) {
if (sscanf(buffer, "targetbase=%s", value) == 1) {
- td->targetbase = misc_strdup(value);
- checkparm++;
+ t = target_at(td, idx[TARGET_BASE]++);
+ if (!t)
+ goto error;
+ t->targetbase = misc_strdup(value);
+ goto found;
}
if (sscanf(buffer, "targettype=%s", value) == 1) {
- type_from_target(value, &td->targettype);
- checkparm++;
+ t = target_at(td, idx[TARGET_TYPE]++);
+ if (!t)
+ goto error;
+ type_from_target(value, &t->targettype);
+ goto found;
}
if (sscanf(buffer, "targetgeometry=%s", value) == 1) {
- td->targetcylinders =
- atoi(strtok(value, ","));
- td->targetheads = atoi(strtok(NULL, ","));
- td->targetsectors = atoi(strtok(NULL, ","));
- checkparm++;
+ t = target_at(td, idx[TARGET_GEOMETRY]++);
+ if (!t)
+ goto error;
+ t->targetcylinders = atoi(strtok(value, ","));
+ t->targetheads = atoi(strtok(NULL, ","));
+ t->targetsectors = atoi(strtok(NULL, ","));
+ goto found;
}
if (sscanf(buffer, "targetblocksize=%s", value) == 1) {
- td->targetblocksize = atoi(value);
- checkparm++;
+ t = target_at(td, idx[TARGET_BLOCKSIZE]++);
+ if (!t)
+ goto error;
+ t->targetblocksize = atoi(value);
+ goto found;
}
if (sscanf(buffer, "targetoffset=%s", value) == 1) {
- td->targetoffset = atol(value);
- checkparm++;
+ t = target_at(td, idx[TARGET_OFFSET]++);
+ if (!t)
+ goto error;
+ t->targetoffset = atol(value);
+ goto found;
}
+ continue;
+found:
+ t->check_params++;
}
- if ((!disk_is_eckd(td->targettype) && checkparm < 4) ||
- (disk_is_eckd(td->targettype) && checkparm != 5)) {
- error_reason("Target parameters missing from script");
- return -1;
+ /* Check for consistency */
+ error = "Inconsistent script output";
+ /*
+ * First, calculate total number of groups
+ */
+ td->nr_targets = 0;
+ for (i = 0; i < MAX_TARGETS; i++) {
+ t = target_at(td, i);
+ if (t->check_params == 0)
+ break;
+ td->nr_targets++;
+ }
+ if (!td->nr_targets)
+ /* No keywords found in the stream */
+ goto error;
+ /*
+ * Each group has to include targetbase, targettype,
+ * targetblocksize and targetoffset.
+ */
+ if (td->nr_targets != idx[TARGET_BASE] ||
+ td->nr_targets != idx[TARGET_TYPE] ||
+ td->nr_targets != idx[TARGET_BLOCKSIZE] ||
+ td->nr_targets != idx[TARGET_OFFSET])
+ goto error;
+ /*
+ * In addition, any group of "ECKD" type has to include
+ * targetgeometry
+ */
+ for (i = 0; i < td->nr_targets; i++) {
+ t = target_at(td, i);
+ assert(t->check_params >= 4);
+ if (disk_is_eckd(t->targettype) && t->check_params != 5)
+ goto error;
}
return 0;
+error:
+ error_reason("%s", error);
+ return -1;
+}
+
+static void print_base_disk_params(struct job_target_data *td, int index)
+{
+ disk_type_t type = get_targettype(td, index);
+
+ if (!verbose)
+ return;
+ {
+ fprintf(stderr, "Base disk '%s':\n", get_targetbase(td, index));
+ fprintf(stderr, " layout........: %s\n", disk_get_type_name(type));
+ }
+ if (disk_is_eckd(type)) {
+ fprintf(stderr, " heads.........: %u\n", get_targetheads(td, index));
+ fprintf(stderr, " sectors.......: %u\n", get_targetsectors(td, index));
+ fprintf(stderr, " cylinders.....: %u\n", get_targetcylinders(td, index));
+ }
+ {
+ fprintf(stderr, " start.........: %lu\n", get_targetoffset(td, index));
+ fprintf(stderr, " blksize.......: %u\n", get_targetblocksize(td, index));
+ }
}
/**
@@ -235,31 +326,57 @@
{
int majnum, minnum;
struct stat stats;
-
+ int i;
+ /*
+ * Currently multiple base disks with different parameters
+ * are not supported
+ */
data->devno = -1;
- data->phy_block_size = td->targetblocksize;
- data->type = td->targettype;
- data->partnum = 0;
+ data->phy_block_size = get_targetblocksize(td, 0);
+ data->type = get_targettype(td, 0);
- if (sscanf(td->targetbase, "%d:%d", &majnum, &minnum) == 2) {
- data->device = makedev(majnum, minnum);
- data->targetbase = defined_as_device;
- data->partnum = minor(stats.st_rdev) - minnum;
- } else {
- if (stat(td->targetbase, &stats)) {
- error_reason(strerror(errno));
- error_text("Could not get information for "
- "file '%s'", td->targetbase);
+ assert(td->nr_targets != 0);
+ for (i = 1; i < td->nr_targets; i++) {
+ if (data->type != get_targettype(td, i) ||
+ data->phy_block_size != get_targetblocksize(td, i)) {
+ print_base_disk_params(td, 0);
+ print_base_disk_params(td, i);
+ error_reason("Inconsistent base disk geometry in target device");
return -1;
}
- if (!S_ISBLK(stats.st_mode)) {
- error_reason("Target base device '%s' is not "
- "a block device",
- td->targetbase);
+ }
+ data->partnum = 0;
+ data->targetbase_def = undefined;
+
+ for (i = 0; i < td->nr_targets; i++) {
+ definition_t defined_as;
+
+ if (sscanf(get_targetbase(td, i),
+ "%d:%d", &majnum, &minnum) == 2) {
+ data->basedisks[i] = makedev(majnum, minnum);
+ defined_as = defined_as_device;
+ } else {
+ if (stat(get_targetbase(td, i), &stats)) {
+ error_reason(strerror(errno));
+ error_text("Could not get information for "
+ "file '%s'", get_targetbase(td, i));
+ return -1;
+ }
+ if (!S_ISBLK(stats.st_mode)) {
+ error_reason("Target base device '%s' is not "
+ "a block device",
+ get_targetbase(td, i));
+ return -1;
+ }
+ data->basedisks[i] = stats.st_rdev;
+ defined_as = defined_as_name;
+ }
+ if (data->targetbase_def != undefined &&
+ data->targetbase_def != defined_as) {
+ error_reason("Target base disks are defined by different ways");
return -1;
}
- data->device = stats.st_rdev;
- data->targetbase = defined_as_name;
+ data->targetbase_def = defined_as;
}
if (data->type == disk_type_scsi && ioctl(fd, NVME_IOCTL_ID) >= 0)
data->is_nvme = 1;
@@ -446,11 +563,28 @@
static int disk_set_geometry_by_hint(struct job_target_data *td,
struct disk_info *data)
{
- data->geo.heads = td->targetheads;
- data->geo.sectors = td->targetsectors;
- data->geo.cylinders = td->targetcylinders;
- data->geo.start = td->targetoffset;
-
+ int i;
+ /*
+ * Currently multiple base disks with different parameters
+ * are not supported
+ */
+ data->geo.heads = get_targetheads(td, 0);
+ data->geo.sectors = get_targetsectors(td, 0);
+ data->geo.cylinders = get_targetcylinders(td, 0);
+ data->geo.start = get_targetoffset(td, 0);
+
+ assert(td->nr_targets != 0);
+ for (i = 1; i < td->nr_targets; i++) {
+ if (data->geo.heads != get_targetheads(td, i) ||
+ data->geo.sectors != get_targetsectors(td, i) ||
+ data->geo.cylinders != get_targetcylinders(td, i) ||
+ data->geo.start != get_targetoffset(td, i)) {
+ print_base_disk_params(td, 0);
+ print_base_disk_params(td, i);
+ error_reason("Inconsistent base disk geometry in target device");
+ return -1;
+ }
+ }
return 0;
}
@@ -515,14 +649,16 @@
}
/**
- * Prepare INFO required to perform IPL installation on the physical
- * disk where the logical DEVICE is located.
+ * Prepare INFO required to perform IPL installation on physical disks
+ * participating in the logical DEVICE.
* Preparation is performed in 2 steps:
*
- * 1. Find out a physical "base" disk where the logical DEVICE is
- * located. Calculate "target" parameters (type, geometry, physical
- * block size, data offset, etc);
- * 2. Complete INFO by the found base disk and target parameters.
+ * 1. Find out a set of physical "base" disks participating in the
+ * logical DEVICE. For each found disk calculate "target" parameters
+ * (type, geometry, physical block size, data offset, etc) and store
+ * it in the array of "targets" of TD;
+ * 2. Complete INFO using the found base disks and calculated target
+ * parameters.
*
* TD: optionally contains target parameters specified by user via
* config file, or special "target options" of zipl tool.
@@ -566,6 +702,7 @@
goto error;
if (disk_set_info_by_hint(td, data, fd))
goto error;
+ data->device = stats.st_rdev;
break;
case source_user:
/*
@@ -578,6 +715,12 @@
goto error;
if (disk_set_info_by_hint(td, data, fd))
goto error;
+ /*
+ * multiple base disks are not supported
+ * with this source type
+ */
+ assert(td->nr_targets == 1);
+ data->device = data->basedisks[0];
break;
case source_auto:
/* no ready target parameters are available */
@@ -585,6 +728,12 @@
goto error;
if (disk_set_info_auto(data, &stats, fd))
goto error;
+ /*
+ * multiple base disks are not supported
+ * with this source type
+ */
+ data->basedisks[0] = data->device;
+ td->nr_targets = 1;
break;
default:
assert(0);
@@ -940,6 +1089,33 @@
printf("%02x:%02x", major(d), minor(d));
}
+void disk_print_devname(dev_t dev)
+{
+ struct util_proc_part_entry part_entry;
+
+ if (!util_proc_part_get_entry(dev, &part_entry)) {
+ printf("%s", part_entry.name);
+ util_proc_part_free_entry(&part_entry);
+ } else {
+ disk_print_devt(dev);
+ }
+}
+
+void prepare_footnote_ptr(int source, char *ptr)
+{
+ if (source == source_user || source == source_script)
+ strcpy(ptr, " *)");
+ else
+ strcpy(ptr, "");
+}
+
+void print_footnote_ref(int source, const char *prefix)
+{
+ if (source == source_user)
+ printf("%s*) Data provided by user.\n", prefix);
+ else if (source == source_script)
+ printf("%s*) Data provided by script.\n", prefix);
+}
/* Return a name for a given disk TYPE. */
char *
@@ -991,12 +1167,11 @@
void disk_print_info(struct disk_info *info, int source)
{
char footnote[4] = "";
- if (source == source_user || source == source_script)
- strcpy(footnote, " *)");
+ prepare_footnote_ptr(source, footnote);
printf(" Device..........................: ");
disk_print_devt(info->device);
- if (info->targetbase == defined_as_device)
+ if (info->targetbase_def == defined_as_device)
printf("%s", footnote);
printf("\n");
if (info->partnum != 0) {
@@ -1007,7 +1182,7 @@
if (info->name) {
printf(" Device name.....................: %s",
info->name);
- if (info->targetbase == defined_as_name)
+ if (info->targetbase_def == defined_as_name)
printf("%s", footnote);
printf("\n");
}
@@ -1050,21 +1225,7 @@
info->phy_block_size, footnote);
printf(" Device size in physical blocks..: %ld\n",
(long) info->phy_blocks);
- if (source == source_user)
- printf(" *) Data provided by user.\n");
- if (source == source_script)
- printf(" *) Data provided by script.\n");
-}
-
-/* Print textual representation of geo structure. */
-void
-disk_print_geo(struct disk_info *data)
-{
- printf(" geo.heads.........:%u\n", data->geo.heads);
- printf(" geo.sectors.......:%u\n", data->geo.sectors);
- printf(" geo.cylinders.....:%u\n", data->geo.cylinders);
- printf(" geo.start.........:%lu\n", data->geo.start);
- printf(" blksize...........:%u\n", data->phy_block_size);
+ print_footnote_ref(source, " ");
}
/* Check whether a block is a zero block which identifies a hole in a file.
--- a/zipl/src/install.c
+++ b/zipl/src/install.c
@@ -434,11 +434,14 @@
{
disk_blockptr_t *scsi_dump_sb_blockptr = &bis->scsi_dump_sb_blockptr;
struct disk_info *info = bis->info;
- char *device = bis->device;
- int fd, rc;
+ char footnote[4];
+ int rc;
+ int i;
if (!info)
return 0;
+
+ prepare_footnote_ptr(job->target.source, footnote);
/* Inform user about what we're up to */
printf("Preparing boot device for %s%s: ",
disk_get_ipl_type(info->type,
@@ -455,40 +458,58 @@
disk_print_devt(info->device);
printf(".\n");
}
- /* Open device file */
- fd = open(device, O_RDWR);
- if (fd == -1) {
- error_reason(strerror(errno));
- error_text("Could not open temporary device file '%s'",
- device);
- return -1;
- }
- /* Ensure that potential cache inconsistencies between disk and
- * partition are resolved by flushing the corresponding buffers. */
- if (!dry_run) {
- if (ioctl(fd, BLKFLSBUF)) {
- fprintf(stderr, "Warning: Could not flush disk "
- "caches.\n");
+ /* Install independently on each physical target base */
+
+ for (i = 0; i < job_get_nr_targets(job); i++) {
+ int fd;
+
+ if (verbose) {
+ printf("Installing on base disk: ");
+ disk_print_devname(info->basedisks[i]);
+ printf("%s.\n", footnote);
}
+ /* Open device file */
+ fd = open(bis->basetmp[i], O_RDWR);
+ if (fd == -1) {
+ error_reason(strerror(errno));
+ error_text("Could not open temporary device file '%s'",
+ bis->basetmp[i]);
+ return -1;
+ }
+ /* Ensure that potential cache inconsistencies between disk and
+ * partition are resolved by flushing the corresponding buffers.
+ */
+ if (!dry_run) {
+ if (ioctl(fd, BLKFLSBUF)) {
+ fprintf(stderr, "Warning: Could not flush disk "
+ "caches.\n");
+ }
+ }
+ /*
+ * Depending on disk type, install one or two program tables
+ * for CCW-type IPL and (or) for List-Directed IPL (see the
+ * picture in comments above)
+ */
+ if (job->id == job_dump_partition) {
+ rc = install_bootloader_dump(bis->tables, info,
+ scsi_dump_sb_blockptr,
+ is_ngdump_enabled(job),
+ fd);
+ } else {
+ rc = install_bootloader_ipl(bis->tables, info,
+ fd);
+ }
+ if (fsync(fd))
+ error_text("Could not sync device file '%s'",
+ bis->basetmp[i]);
+ if (close(fd))
+ error_text("Could not close device file '%s'",
+ bis->basetmp[i]);
+ if (rc)
+ break;
}
- /*
- * Depending on disk type, install one or two program tables
- * for CCW-type IPL and (or) for List-Directed IPL (see the
- * picture in comments above)
- */
- if (job->id == job_dump_partition) {
- rc = install_bootloader_dump(bis->tables, info,
- scsi_dump_sb_blockptr,
- is_ngdump_enabled(job),
- fd);
- } else {
- rc = install_bootloader_ipl(bis->tables, info, fd);
- }
-
- if (fsync(fd))
- error_text("Could not sync device file '%s'", device);
- if (close(fd))
- error_text("Could not close device file '%s'", device);
+ if (verbose)
+ print_footnote_ref(job->target.source, "");
if (!dry_run && rc == 0) {
if (info->devno >= 0)
--- a/zipl/src/job.c
+++ b/zipl/src/job.c
@@ -1346,6 +1346,27 @@
}
}
+int set_targettype(struct job_target_data *data, int index, char *value)
+{
+ return type_from_target(value,
+ &target_at(data, index)->targettype);
+}
+
+int job_set_targettype(struct job_data *job, char *value)
+{
+ return set_targettype(&job->target, 0, value);
+}
+
+static int job_set_target(struct job_data *job, char *value)
+{
+ job_set_targetbase(job, value);
+ if (!job_get_targetbase(job))
+ return -1;
+ job_set_nr_targets(job, 1);
+ job->target.source = source_user;
+ return 0;
+}
+
static int
get_job_from_section_data(char* data[], struct job_data* job, char* section)
{
@@ -1362,32 +1383,28 @@
return -1;
/* Fill in target */
if (data[(int) scan_keyword_targetbase] != NULL) {
- job->target.targetbase =
- misc_strdup(data[(int)
- scan_keyword_targetbase]);
- if (job->target.targetbase == NULL)
+ if (job_set_target(job, misc_strdup(data[(int)
+ scan_keyword_targetbase])))
return -1;
- job->target.source = source_user;
}
if (data[(int) scan_keyword_targettype] != NULL) {
- if (type_from_target(
- data[(int) scan_keyword_targettype],
- &job->target.targettype))
+ if (job_set_targettype(job,
+ data[(int) scan_keyword_targettype]))
return -1;
}
if (data[(int) scan_keyword_targetgeometry] != NULL) {
- job->target.targetcylinders =
+ job_set_targetcylinders(job,
atoi(strtok(data[(int)
- scan_keyword_targetgeometry], ","));
- job->target.targetheads = atoi(strtok(NULL, ","));
- job->target.targetsectors = atoi(strtok(NULL, ","));
+ scan_keyword_targetgeometry], ",")));
+ job_set_targetheads(job, atoi(strtok(NULL, ",")));
+ job_set_targetsectors(job, atoi(strtok(NULL, ",")));
}
if (data[(int) scan_keyword_targetblocksize] != NULL)
- job->target.targetblocksize =
- atoi(data[(int) scan_keyword_targetblocksize]);
+ job_set_targetblocksize(job,
+ atoi(data[(int) scan_keyword_targetblocksize]));
if (data[(int) scan_keyword_targetoffset] != NULL)
- job->target.targetoffset =
- atol(data[(int) scan_keyword_targetoffset]);
+ job_set_targetoffset(job,
+ atol(data[(int) scan_keyword_targetoffset]));
/* Fill in name and address of image file */
job->data.ipl.common.image = misc_strdup(
@@ -1615,37 +1632,32 @@
return -1;
break;
case scan_keyword_targetbase:
- job->target.targetbase = misc_strdup(
- scan[i].content.keyword.value);
- if (job->target.targetbase == NULL)
+ if (job_set_target(job, misc_strdup(
+ scan[i].content.keyword.value)))
return -1;
- job->target.source = source_user;
break;
case scan_keyword_targettype:
- if (type_from_target(
- scan[i].content.keyword.value,
- &job->target.targettype))
+ if (job_set_targettype(job,
+ scan[i].content.keyword.value))
return -1;
break;
case scan_keyword_targetgeometry:
- job->target.targetcylinders =
+ job_set_targetcylinders(job,
atoi(strtok(
scan[i].content.keyword.value,
- ","));
- job->target.targetheads =
- atoi(strtok(NULL, ","));
- job->target.targetsectors =
- atoi(strtok(NULL, ","));
+ ",")));
+ job_set_targetheads(job,
+ atoi(strtok(NULL, ",")));
+ job_set_targetsectors(job,
+ atoi(strtok(NULL, ",")));
break;
case scan_keyword_targetblocksize:
- job->target.targetblocksize =
- atoi(
- scan[i].content.keyword.value);
+ job_set_targetblocksize(job, atoi(
+ scan[i].content.keyword.value));
break;
case scan_keyword_targetoffset:
- job->target.targetoffset =
- atol(
- scan[i].content.keyword.value);
+ job_set_targetoffset(job, atol(
+ scan[i].content.keyword.value));
break;
default:
/* Should not happen */

View File

@ -0,0 +1,15 @@
--- a/zipl/src/job.c 2024-09-16 14:20:09.321762661 +0200
+++ b/zipl/src/job.c 2024-09-16 14:29:28.601846724 +0200
@@ -373,8 +373,11 @@
static void
free_target_data(struct job_target_data* data)
{
+ int i;
+
free(data->bootmap_dir);
- free(data->targetbase);
+ for (i = 0; i < data->nr_targets; i++)
+ free(get_targetbase(data, i));
}
static void

BIN
s390-tools-2.31.0.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,51 @@
From 6a55d0c2e57952600164822dd100e8247b4b010f Mon Sep 17 00:00:00 2001
From: Steffen Eiden <seiden@linux.ibm.com>
Date: Fri, 23 Aug 2024 09:16:26 +0200
Subject: [PATCH] rust/pv: Lower most lints to warn
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Lower the lint level to warn for the styling lints.
This avoids compile issues during packaging for newer tooling with
potential more lint findings.
Still deny compiling if a public symbol has no documentation.
Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/173
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
rust/pv/src/lib.rs | 4 ++--
rust/pv_core/src/lib.rs | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/rust/pv/src/lib.rs b/rust/pv/src/lib.rs
index 9a647617..1084f8e8 100644
--- a/rust/pv/src/lib.rs
+++ b/rust/pv/src/lib.rs
@@ -2,8 +2,8 @@
//
// Copyright IBM Corp. 2023, 2024
-#![deny(
- missing_docs,
+#![deny(missing_docs)]
+#![warn(
missing_debug_implementations,
trivial_numeric_casts,
unstable_features,
diff --git a/rust/pv_core/src/lib.rs b/rust/pv_core/src/lib.rs
index 1356c1b7..b617b8f9 100644
--- a/rust/pv_core/src/lib.rs
+++ b/rust/pv_core/src/lib.rs
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2023, 2024
-#![deny(
- missing_docs,
+#![deny(missing_docs)]
+#![warn(
missing_debug_implementations,
trivial_numeric_casts,
unstable_features,

3
s390-tools-2.34.0.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ea4758c4e460d7f7e040e6aedf68b1be32d63fecb733358b08182f6b9b7440a2
size 2114507

BIN
s390-tools-2.35.0.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,133 @@
---
zdev/dracut/96zdev-live/module-setup.sh | 32 +++++++++++++++++++++++++
zdev/dracut/96zdev-live/parse-zdev-live.sh | 36 +++++++++++++++++++++++++++++
zdev/dracut/96zdev-live/write-udev-live.sh | 11 ++++++++
zdev/dracut/Makefile | 15 ++++++++++--
4 files changed, 92 insertions(+), 2 deletions(-)
--- /dev/null
+++ b/zdev/dracut/96zdev-live/module-setup.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1
+
+ require_binaries chzdev || return 1
+
+ [[ $hostonly ]] || return 0
+
+ # or on request
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo bash
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods ctcm lcs qeth qeth_l2 qeth_l3 dasd_diag_mod dasd_eckd_mod dasd_fba_mod
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 41 "$moddir/parse-zdev-live.sh"
+ inst_hook cleanup 41 "$moddir/write-udev-live.sh"
+ inst_multiple chzdev
+}
--- /dev/null
+++ b/zdev/dracut/96zdev-live/parse-zdev-live.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+#
+# 96zdev-live/parse-zdev-live.sh
+# Parse the kernel command line for rd.zdev kernel parameters. These
+# parameters are evaluated and used to configure z Systems specific devices
+# with chzdev(8), especially for use on live/installation type media.
+# Note: this is only active on no-hostonly initrds (by default).
+#
+# Format:
+# rd.zdev=TYPE,DEVICE[,SETTINGS]
+#
+# where
+#
+# TYPE: all device types supported by chzdev(8), like qeth and dasd
+# DEVICE: device specification as supported by chzdev(8) '--enable',
+# with the exception of specifying multiple devices, which
+# need to be separated by commas. Channel group members
+# (or zFCP parameters) in turn are separated by colons.
+# SETTINGS: Settings are positional arguments of chzdev in the form
+# KEY=VALUE separated by commas.
+
+zdev_enable="--persistent --enable"
+zdev_base_args="--yes --no-root-update --no-settle"
+
+for zdevs in $(getargs rd.zdev) ; do
+ IFS=',' read -r -a zdev <<< "$zdevs"
+ if [ -n "$zdev" ] && [ "$zdev" = "no-auto" -o "$zdev" = "auto" ] ; then
+ : # ignore, as it's handled by 95zdev
+ elif [ -z "$zdev" ] || [ -z "${zdev[1]}" ] ; then
+ warn "Unsupported usage of rd.zdev=$zdevs"
+ else
+ info "+ chzdev $zdev_enable [...] ${zdev[@]}"
+ chzdev $zdev_enable $zdev_base_args "${zdev[@]}"
+ fi
+done
+
--- /dev/null
+++ b/zdev/dracut/96zdev-live/write-udev-live.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+#
+# 96zdev-live/write-udev-live.sh
+# Copy udeve rules generated by chzdev for device activation starting with 41
+# to a *writable* /sysroot -- this is primarily useful for live/installation-
+# type media (and by default only active on no-hostonly initrds)
+#
+
+if [ -w /sysroot/etc/udev/rules.d ]; then
+ cp -p /etc/udev/rules.d/41-* /sysroot/etc/udev/rules.d
+fi
--- a/zdev/dracut/Makefile
+++ b/zdev/dracut/Makefile
@@ -3,17 +3,23 @@
ZDEVDIR := 95zdev
ZDEVKDUMPDIR := 95zdev-kdump
+ZDEVLIVEDIR := 96zdev-live
# HAVE_DRACUT
#
-# This install time parameter determines whether the zdev dracut module is
-# installed (HAVE_DRACUT=1) or not (default). When installed, the module
+# This install time parameter determines whether the zdev dracut modules are
+# installed (HAVE_DRACUT=1) or not (default). When installed, the 95zdev module
# performs the following functions when dracut is run:
#
# - copy the persistent root device configuration to the initial ram disk
# - install a boot-time hook to apply firmware-provided configuration data
# to the system
#
+# The 96zdev-live module performs the following functions when dracut is run:
+#
+# - install a boot-time hook to apply command-line-provided configuration data
+# to a no-hostonly built initial ram disk for use in live/installation media
+#
ifeq ($(HAVE_DRACUT),1)
install:
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/
@@ -29,4 +35,9 @@
$(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/$(ZDEVKDUMPDIR)
$(INSTALL) -m 755 $(ZDEVKDUMPDIR)/module-setup.sh \
$(DESTDIR)$(DRACUTMODDIR)/$(ZDEVKDUMPDIR)/
+ $(INSTALL) -m 755 -d $(DESTDIR)$(DRACUTMODDIR)/$(ZDEVLIVEDIR)
+ $(INSTALL) -m 755 $(ZDEVLIVEDIR)/module-setup.sh \
+ $(ZDEVLIVEDIR)/parse-zdev-live.sh \
+ $(ZDEVLIVEDIR)/write-udev-live.sh \
+ $(DESTDIR)$(DRACUTMODDIR)/$(ZDEVLIVEDIR)/
endif

6
s390-tools-rpmlintrc Normal file
View File

@ -0,0 +1,6 @@
addFilter("statically-linked-binary /usr/lib/s390-tools/.*")
addFilter("statically-linked-binary /usr/bin/read_values")
addFilter("systemd-service-without-service_.* *@.service")
addFilter("position-independent-executable-suggested ")
addFilter("non-etc-or-var-file-marked-as-conffile /boot/zipl/active_devices.txt")
addFilter("zero-length /boot/zipl/active_devices.txt")

View File

@ -0,0 +1,30 @@
---
etc/udev/rules.d/59-dasd.rules | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
--- a/etc/udev/rules.d/59-dasd.rules
+++ b/etc/udev/rules.d/59-dasd.rules
@@ -15,7 +15,7 @@
LABEL="dasd_block_end"
-ACTION!="change|add", GOTO="dasd_symlinks_end"
+ACTION!="change|add", GOTO="dasd_partition_end"
# for partitions import parent information
KERNEL=="dasd*[0-9]", IMPORT{parent}=="ID_*"
@@ -24,6 +24,14 @@
KERNEL=="dasd*[0-9]", ENV{ID_UID}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_UID}-part%n"
KERNEL=="dasd*[0-9]", ENV{ID_XUID}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_XUID}-part%n"
+LABEL="dasd_partition_end"
+
+ENV{ID_SERIAL}!="?*", GOTO="dasd_symlinks_end"
+# by-label/by-uuid (filesystem properties)
+IMPORT{builtin}="blkid"
+ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID}"
+ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_SAFE}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_SAFE}"
+
LABEL="dasd_symlinks_end"
# on device add set request queue scheduler to none

View File

@ -0,0 +1,33 @@
From d0c2ffc90b9ee0e7b741d1c4b644cdf79f1d922b Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Wed, 20 May 2015 11:57:11 +0200
Subject: [PATCH] fdasd: skip partition check and BLKRRPART ioctl for emulated
devices
If 'fdasd -f' is called we cannot rely on the partition detection
via a simple check of the minor number, so the check should be
suppressed.
Similarly, not every emulated device supports the BLKRRPART ioctl,
so we should be suppressing the error message for these devices, too.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
fdasd/fdasd.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fdasd/fdasd.c
+++ b/fdasd/fdasd.c
@@ -1231,10 +1231,12 @@
*/
static void fdasd_reread_partition_table(fdasd_anchor_t *anc)
{
+ int rc = 0 ;
if (!anc->silent)
printf("rereading partition table...\n");
- if (dasd_reread_partition_table(options.device, 5) != 0) {
+ rc = dasd_reread_partition_table(options.device, 1);
+ if (rc == EINVAL && !anc->force_virtual) {
fdasd_error(anc, unable_to_ioctl, "Error while rereading "
"partition table.\nPlease reboot!");
}

View File

@ -0,0 +1,34 @@
From f7a0f391f2c4e8acc96b21ab5de54a178aa60088 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 22 Nov 2013 15:39:38 +0100
Subject: [PATCH] 59-dasd.rules: generate by-id links on 'change' and 'add'
The by-id rules need to be triggered on both, 'change' and 'add',
to work correctly during restarting udev.
References: bnc#808042
Signed-off-by: Robert Milasan <rmilasan@suse.de>
---
etc/udev/rules.d/59-dasd.rules | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/etc/udev/rules.d/59-dasd.rules b/etc/udev/rules.d/59-dasd.rules
index 2b1435c..a08cb7c 100644
--- a/etc/udev/rules.d/59-dasd.rules
+++ b/etc/udev/rules.d/59-dasd.rules
@@ -6,9 +6,9 @@
SUBSYSTEM!="block", GOTO="dasd_symlinks_end"
KERNEL!="dasd*", GOTO="dasd_symlinks_end"
-ACTION!="change", GOTO="dasd_block_end"
+ACTION!="change|add", GOTO="dasd_block_end"
# by-id (hardware serial number)
-KERNEL=="dasd*[!0-9]", ATTRS{status}=="online", IMPORT{program}="/sbin/dasdinfo -a -e -b $kernel"
+KERNEL=="dasd*[!0-9]", ATTRS{status}=="online", IMPORT{program}="/usr/sbin/dasdinfo -a -e -b $kernel"
KERNEL=="dasd*[!0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
KERNEL=="dasd*[!0-9]", ENV{ID_UID}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_UID}"
KERNEL=="dasd*[!0-9]", ENV{ID_XUID}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_XUID}"
--
1.8.1.4

View File

@ -0,0 +1,26 @@
From f7a0f391f2c4e8acc96b21ab5de54a178aa60088 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 22 Nov 2013 15:39:38 +0100
Subject: [PATCH] 59-dasd.rules: generate by-id links on 'change' and 'add'
The by-id rules need to be triggered on both, 'change' and 'add',
to work correctly during restarting udev.
References: bnc#808042
Signed-off-by: Robert Milasan <rmilasan@suse.de>
---
etc/udev/rules.d/59-dasd.rules | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/etc/udev/rules.d/59-dasd.rules
+++ b/etc/udev/rules.d/59-dasd.rules
@@ -6,7 +6,7 @@
SUBSYSTEM!="block", GOTO="dasd_symlinks_end"
KERNEL!="dasd*", GOTO="dasd_symlinks_end"
-ACTION!="change", GOTO="dasd_block_end"
+ACTION!="change|add", GOTO="dasd_block_end"
# by-id (hardware serial number)
KERNEL=="dasd*[!0-9]", ATTRS{status}=="online", IMPORT{program}="/sbin/dasdinfo -a -e -b $kernel"
KERNEL=="dasd*[!0-9]", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"

View File

@ -0,0 +1,20 @@
---
zipl/boot/menu.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/zipl/boot/menu.c
+++ b/zipl/boot/menu.c
@@ -168,8 +168,11 @@
/* print config list */
menu_list();
- if (is_zvm())
- printf("Note: VM users please use '#cp vi vmsg <input>'\n");
+ if (is_zvm()) {
+ printf(" \n");
+ printf("Note: VM users please use '#cp vi vmsg <input> <kernel-parameters>'\n");
+ printf(" \n");
+ }
value = menu_read();

View File

@ -0,0 +1,148 @@
---
etc/sysconfig/dumpconf | 133 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 133 insertions(+)
--- a/etc/sysconfig/dumpconf
+++ b/etc/sysconfig/dumpconf
@@ -1,3 +1,4 @@
+###########################################################################################
#
# s390 dump config
#
@@ -78,3 +79,135 @@
# dumpconf becomes active immediately during system startup.
#
# ON_PANIC=reipl
+
+############################ Begin Definitions ###########################################
+## Path: System/Dumpconf
+## Description: Configures the actions which should be performed after a kernel panic
+## Type: list(stop,dump,vmcmd,reipl,dump_reipl)
+## Default: "stop"
+## ServiceRestart: dumpconf
+#
+# Define the action that should be taken if a kernel panic happens.
+#
+ON_PANIC="stop"
+
+## Type: integer(0:300)
+## Default: 5
+## ServiceRestart: dumpconf
+#
+# Using reipl or dump_reipl actions with ON_PANIC can lead to the system
+# looping with alternating IPLs and crashes. Use DELAY_MINUTES to prevent
+# such a loop. DELAY_MINUTES delays activating the specified panic action
+# for a newly started system. When the specified time has elapsed, dumpconf
+# activates the specified panic action. This action is taken should the
+# system subsequently crash. If the system crashes before the time has
+# elapsed the previously defined action is taken. If no previous action has
+# been defined the default action (STOP) is performed.
+#
+DELAY_MINUTES="5"
+
+## Type: list(ccw,fcp,nvme)
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the type, ccw for DASD, fcp for zFCP, or nvme for NVMe Disk.
+#
+DUMP_TYPE=""
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the device id for a DASD or SCSI over zFCP dump device.
+#
+# For example (DASD and SCSI over zFCP have the same structure): DEVICE=0.0.4711
+#
+DEVICE=""
+
+# Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the WWPN for a zFCP dump device.
+#
+# For example: WWPN=0x5005076303004711
+#
+WWPN=""
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the LUN for a zFCP dump device.
+#
+# For example: LUN=0x4711000000000000
+#
+LUN=""
+
+## Type: integer(0:30)
+## Default: "0"
+## ServiceRestart: dumpconf
+#
+# Define the Boot program selector for a zFCP dump device.
+#
+# A decimal value between 0 and 30 specifying the program to be loaded from
+# the FCP-I/O device.
+#
+BOOTPROG="0"
+
+## Type: string
+## Default: "0"
+## ServiceRestart: dumpconf
+#
+# Define the Boot record logical block address for a zFCP dump device.
+#
+# The hexadecimal digits designating the logical-block address of the boot record of the FCP-I/O device.
+# It must be a value from 0-FFFFFFFF FFFFFFFF. For values longer than 8 hex characters at least one separator
+# blank is required after the 8th character.
+#
+BR_LBA="0"
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the Function ID for NVMe dump device.
+#
+# The hexadecimal digits designating the Function ID for the NMVe disk.
+#
+# For example: FID=0x00000300
+#
+FID=""
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the Namespace ID for the NVMe dump device
+#
+# The hexadecimal digits designating the Namespace ID for the NMVe disk.
+#
+# For example: NSID=0x00000001
+#
+NSID=""
+
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# VMCMD_<X>
+# Specifies a CP command, <X> is a number from one to eight. You can
+# specify up to eight CP commands that are executed in case of a kernel
+# panic. Note that VM commands, device adresses, and VM guest names
+# must be uppercase.
+#
+VMCMD_1=""
+VMCMD_2=""
+VMCMD_3=""
+VMCMD_4=""
+VMCMD_5=""
+VMCMD_6=""
+VMCMD_7=""
+VMCMD_8=""
+
+############################### End Definitions ##############################################
\ No newline at end of file

View File

@ -0,0 +1,50 @@
Subject: zdev: Add support for handling I/O configuration data
From: Peter Oberparleiter <oberpar@linux.ibm.com>
Summary: zdev: Add support for handling I/O configuration data
Description: LPARs that are running in IBM Dynamic Partition Manager (DPM) mode
can access a firmware-generated I/O configuration data file that
contains s390-specific information about available I/O devices
such as qeth device numbers and parameters, and FCP device IDs.
This data file is intended to remove the need for users to
manually enter the corresponding device data during installation.
Linux kernels with the corresponding support make the I/O
configuration data available at the following location:
/sys/firmware/sclp_sd/config/data
This patch set adds support for handling this data file using the
chzdev and lszdev tools:
- I/O configuration data can be applied using chzdev's --import
option
- Initial RAM-Disk scripts automatically apply the
I/O configuration data to the system configuration
- lszdev can be used to display the applied auto-configuration
data
- chzdev can be used to manually override the
auto-configuration data
Upstream-ID: -
Problem-ID: LS1604
Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com>
---
zdev/src/zdev-root-update.dracut | 6 ------
1 file changed, 6 deletions(-)
--- a/zdev/src/zdev-root-update.dracut
+++ b/zdev/src/zdev-root-update.dracut
@@ -20,10 +20,4 @@
exit 1
}
-echo "Installing IPL record"
-zipl --noninteractive || {
- echo "${TOOLNAME}: Error: Could not install IPL record" >&2
- exit 1
-}
-
exit 0

View File

@ -0,0 +1,465 @@
From d6582bbaf0f3986a42f562046dc0caa9de89c75e Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 6 Oct 2017 08:58:17 +0200
Subject: [PATCH] dasdfmt: Allow multiple device arguments
Allow the user to specify several devices as arguments to dasdfmt.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
dasdfmt/dasdfmt.8 | 6 -
dasdfmt/dasdfmt.c | 197 +++++++++++++++++++++++++++++++-----------------------
2 files changed, 119 insertions(+), 84 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -11,14 +11,14 @@
.br
[\-r \fIcylinder\fR] [\-b \fIblksize\fR] [\-l \fIvolser\fR] [\-d \fIlayout\fR]
.br
- [\-L] [\-V] [\-F] [\-k] [\-C] [\-M \fImode\fR] \fIdevice\fR
+ [\-L] [\-V] [\-F] [\-k] [\-C] [\-M \fImode\fR] \fIdevice\fR [\fIdevice\fR]
.SH DESCRIPTION
-\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
+\fBdasdfmt\fR formats one or several DASD (ECKD) disk drive(s) to prepare them
for usage with Linux for S/390.
The \fIdevice\fR is the node of the device (e.g. '/dev/dasda').
Any device node created by udev for kernel 2.6 can be used
-(e.g. '/dev/dasd/0.0.b100/disc').
+(e.g. '/dev/dasd/0.0.b100/disc'). It is possible to specify up to 512 devices.
.br
\fBWARNING\fR: Careless usage of \fBdasdfmt\fR can result in
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -25,6 +25,8 @@
#include "dasdfmt.h"
+#define MAX_DEVICES 512
+#define MAX_LENGTH 256
#define BUSIDSIZE 8
#define SEC_PER_DAY (60 * 60 * 24)
#define SEC_PER_HOUR (60 * 60)
@@ -57,7 +59,9 @@
static struct dasdfmt_globals {
dasd_information2_t dasd_info;
char *dev_path; /* device path entered by user */
+ char dev_path_array[MAX_DEVICES][MAX_LENGTH]; /* Array of device paths entered by user */
char *dev_node; /* reliable device node determined by dasdfmt */
+ char dev_node_array[MAX_DEVICES][MAX_LENGTH]; /* Array of reliable device nodes determined by dasdfmt */
int verbosity;
int testmode;
int withoutprompt;
@@ -484,15 +488,15 @@
program_interrupt_in_progress = 1;
if (disk_disabled) {
- printf("Re-accessing the device...\n");
+ printf("Re-accessing %s...\n", g.dev_path);
disk_enable();
}
- printf("Rereading the partition table...\n");
+ printf("Rereading the partition table for %s...\n", g.dev_path);
rc = dasd_reread_partition_table(g.dev_node, 5);
if (rc) {
ERRMSG("%s: (signal handler) Re-reading partition table "
- "failed. (%s)\n", prog_name, strerror(rc));
+ "for %s failed. (%s)\n", prog_name, g.dev_path, strerror(rc));
} else {
printf("Exiting...\n");
}
@@ -512,9 +516,6 @@
unsigned int maj, min;
struct stat dev_stat;
- if (optind + 1 < argc)
- error("More than one device specified!");
-
if (optind >= argc)
error("No device specified!");
@@ -610,10 +611,10 @@
error("the ioctl call to retrieve read/write status information failed: %s",
strerror(err));
if (ro)
- error("Disk is read only!");
+ error("Disk %s is read only!", g.dev_path);
if (!g.force) {
if (g.dasd_info.open_count > 1)
- error("Disk in use!");
+ error("Disk %s is in use!", g.dev_path);
}
if (strncmp(g.dasd_info.type, "ECKD", 4) != 0) {
warnx("Unsupported disk type");
@@ -700,7 +701,7 @@
struct dasd_eckd_characteristics *characteristics;
if (g.verbosity > 0)
- printf("Retrieving disk geometry...\n");
+ printf("Retrieving disk geometry for %s...\n", g.dev_path);
characteristics = (struct dasd_eckd_characteristics *)
&g.dasd_info.characteristics;
@@ -728,13 +729,13 @@
"Cylinders above this limit will not be"
" accessible as a linux partition!\n"
"Type \"yes\" to continue, no will leave"
- " the disk untouched: ", LV_COMPAT_CYL);
+ " the %s disk untouched: ", LV_COMPAT_CYL, g.dev_path);
if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
return;
if (strcasecmp(inp_buffer, "yes") &&
strcasecmp(inp_buffer, "yes\n")) {
- printf("Omitting ioctl call (disk will "
- "NOT be formatted).\n");
+ printf("Omitting ioctl call (disk %s will "
+ "NOT be formatted).\n", g.dev_path);
return;
}
}
@@ -872,7 +873,7 @@
check_params->start_unit = 0;
check_params->stop_unit = (cylinders * heads) - 1;
- printf("Checking format of the entire disk...\n");
+ printf("Checking format of the entire %s disk...\n", g.dev_path);
if (g.testmode) {
printf("Test mode active, omitting ioctl.\n");
@@ -896,7 +897,7 @@
if (process_tracks(cylinders, heads, check_params))
error("Use --mode=full to perform a clean format.");
- printf("Done. Disk is fine.\n");
+ printf("Done. Disk %s is fine.\n", g.dev_path);
}
/*
@@ -946,8 +947,8 @@
printf("Device Type: %s Provisioned\n",
g.ese ? "Thinly" : "Fully");
- printf("\nI am going to format the device ");
- printf("%s in the following way:\n", g.dev_path);
+ printf("\nI am going to format %s ", g.dev_path);
+ printf("in the following way:\n");
printf(" Device number of device : 0x%x\n", g.dasd_info.devno);
printf(" Labelling device : %s\n",
(g.writenolabel) ? "no" : "yes");
@@ -1012,7 +1013,7 @@
int ipl1_record_len, ipl2_record_len;
if (g.verbosity > 0)
- printf("Retrieving dasd information... ");
+ printf("Retrieving dasd information for %s... ", g.dev_path);
get_blocksize(&blksize);
@@ -1030,7 +1031,7 @@
/* write empty bootstrap (initial IPL records) */
if (g.verbosity > 0)
- printf("Writing empty bootstrap...\n");
+ printf("Writing empty bootstrap to %s...\n", g.dev_path);
/*
* Note: ldl labels do not contain the key field
@@ -1089,7 +1090,7 @@
label_position = g.dasd_info.label_block * blksize;
if (g.verbosity > 0)
- printf("Writing label...\n");
+ printf("Writing label to %s...\n", g.dev_path);
rc = lseek(fd, label_position, SEEK_SET);
if (rc != label_position) {
@@ -1120,7 +1121,7 @@
}
if (g.verbosity > 0)
- printf("Writing VTOC... ");
+ printf("Writing VTOC to %s... ", g.dev_path);
label_position = (VTOC_START_CC * heads + VTOC_START_HH) *
geo.sectors * blksize;
@@ -1242,7 +1243,7 @@
if (!g.ese || g.no_discard)
return;
- printf("Releasing space for the entire device...\n");
+ printf("Releasing space for the entire %s device...\n", g.dev_path);
err = dasd_release_space(g.dev_node, &r);
if (err)
error("Could not release space: %s", strerror(err));
@@ -1261,20 +1262,21 @@
int err;
if (!(g.withoutprompt && g.verbosity < 1))
- printf("Formatting the device. This may take a while "
- "(get yourself a coffee).\n");
+ printf("Formatting the %s device. This may take a while "
+ "(get yourself a coffee).\n", g.dev_path);
if (g.verbosity > 0)
- printf("Detaching the device...\n");
+ printf("Detaching the %s device...\n", g.dev_path);
disk_disable(g.dev_node);
if (g.verbosity > 0)
- printf("Invalidate first track...\n");
+ printf("Invalidate first track on %s...\n", g.dev_path);
err = dasd_format_disk(filedes, &temp);
if (err != 0)
- error("(invalidate first track) IOCTL BIODASDFMT failed: %s", strerror(err));
+ error("(invalidate first track) IOCTL BIODASDFMT failed for %s: %s",
+ g.dev_path, strerror(err));
/* except track 0 from standard formatting procss */
p->start_unit = 1;
@@ -1282,19 +1284,19 @@
process_tracks(cylinders, heads, p);
if (g.verbosity > 0)
- printf("formatting tracks complete...\n");
+ printf("formatting tracks for %s complete...\n", g.dev_path);
temp.intensity = p->intensity;
if (g.verbosity > 0)
- printf("Revalidate first track...\n");
+ printf("Revalidate first track on %s...\n", g.dev_path);
err = dasd_format_disk(filedes, &temp);
if (err != 0)
error("(re-validate first track) IOCTL BIODASDFMT failed: %s", strerror(err));
if (g.verbosity > 0)
- printf("Re-accessing the device...\n");
+ printf("Re-accessing the %s device...\n", g.dev_path);
disk_enable();
}
@@ -1306,18 +1308,18 @@
format_data_t *p)
{
if (!(g.withoutprompt && g.verbosity < 1))
- printf("Formatting the device. This may take a while "
- "(get yourself a coffee).\n");
+ printf("Formatting the %s device. This may take a while "
+ "(get yourself a coffee).\n", g.dev_path);
if (g.verbosity > 0)
- printf("Detaching the device...\n");
+ printf("Detaching the %s device...\n", g.dev_path);
disk_disable(g.dev_node);
process_tracks(cylinders, heads, p);
if (g.verbosity > 0)
- printf("Formatting tracks complete...\n");
+ printf("formatting tracks for %s complete...\n", g.dev_path);
if (g.verbosity > 0)
printf("Re-accessing the device...\n");
@@ -1426,16 +1428,16 @@
if (!g.withoutprompt) {
printf("\n");
if (mode != EXPAND)
- printf("--->> ATTENTION! <<---\nAll data of "
- "that device will be lost.\n");
+ printf("--->> ATTENTION! <<---\nAll data on "
+ "the %s device will be lost.\n", g.dev_path);
printf("Type \"yes\" to continue, no will leave the "
"disk untouched: ");
if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
return;
if (strcasecmp(inp_buffer, "yes") &&
strcasecmp(inp_buffer, "yes\n")) {
- printf("Omitting ioctl call (disk will "
- "NOT be formatted).\n");
+ printf("Omitting ioctl call (disk %s will "
+ "NOT be formatted).\n", g.dev_path);
return;
}
}
@@ -1453,12 +1455,12 @@
break;
}
- printf("Finished formatting the device.\n");
+ printf("Finished formatting the %s device.\n", g.dev_path);
if (!(g.writenolabel || mode == EXPAND))
dasdfmt_write_labels(vlabel, cylinders, heads);
- printf("Rereading the partition table... ");
+ printf("Rereading the partition table for %s... ", g.dev_path);
err = dasd_reread_partition_table(g.dev_node, 5);
if (err != 0) {
ERRMSG("%s: error during rereading the partition "
@@ -1472,7 +1474,7 @@
static void eval_format_mode(void)
{
if (!g.force && g.mode_specified && g.ese && mode == EXPAND) {
- warnx("WARNING: The specified device is thin-provisioned");
+ warnx("WARNING: The specified device, %s, is thin-provisioned", g.dev_path);
warnx("Format mode 'expand' is not feasible.");
error("Use --mode=full or --mode=quick to perform a clean format");
}
@@ -1495,20 +1497,70 @@
prog_name = p + 1;
}
-int main(int argc, char *argv[])
+void process_dasd(volume_label_t *orig_vlabel, format_data_t format_params)
{
volume_label_t vlabel;
char old_volser[7];
-
char str[ERR_LENGTH];
+ unsigned int cylinders, heads; int rc;
+
+ rc = dasd_get_info(g.dev_node, &g.dasd_info);
+ if (rc != 0)
+ error("the ioctl call to retrieve device information failed: %s", strerror(rc));
+
+ g.ese = dasd_sys_ese(g.dev_node);
+ eval_format_mode();
+
+ /* Not sure this next line is needed in the new version of the code. */
+ memcpy(&vlabel, orig_vlabel, sizeof(vlabel));
+
+ /* Either let the user specify the blksize or get it from the kernel */
+ if (!g.blksize_specified) {
+ if (!(mode == FULL ||
+ g.dasd_info.format == DASD_FORMAT_NONE) || g.check)
+ get_blocksize(&format_params.blksize);
+ else
+ format_params = ask_user_for_blksize(format_params);
+ }
+
+ if (g.keep_volser) {
+ if (g.labelspec)
+ error("The -k and -l options are mutually exclusive");
+ if (!(format_params.intensity & DASD_FMT_INT_COMPAT))
+ error("WARNING: VOLSER cannot be kept when using the ldl format!");
+
+ if (dasdfmt_get_volser(old_volser) == 0)
+ vtoc_volume_label_set_volser(&vlabel, old_volser);
+ else
+ error("VOLSER not found on device %s", g.dev_path);
+ }
+
+ check_disk();
+
+ if (check_param(str, ERR_LENGTH, &format_params) < 0)
+ error("%s", str);
+
+ set_geo(&cylinders, &heads);
+ set_label(&vlabel, &format_params, cylinders);
+
+ if (g.check)
+ check_disk_format(cylinders, heads, &format_params);
+ else
+ do_format_dasd(&vlabel, &format_params, cylinders, heads);
+
+}
+
+int main(int argc, char *argv[])
+{
+ volume_label_t vlabel;
+
char buf[7];
char *blksize_param_str = NULL;
char *reqsize_param_str = NULL;
char *hashstep_str = NULL;
- int rc;
- unsigned int cylinders, heads;
+ int rc, numdev = 0, i;
/* Establish a handler for interrupt signals. */
signal(SIGTERM, program_interrupt_signal);
@@ -1644,6 +1696,9 @@
break; /* exit loop if finished */
}
+ /* Reset the value of rc since we're going to use it again later. */
+ rc = 0;
+
CHECK_SPEC_MAX_ONCE(g.blksize_specified, "blocksize");
CHECK_SPEC_MAX_ONCE(g.labelspec, "label");
CHECK_SPEC_MAX_ONCE(g.writenolabel, "omit-label-writing flag");
@@ -1662,48 +1717,28 @@
if (g.print_hashmarks)
PARSE_PARAM_INTO(g.hashstep, hashstep_str, 10, "hashstep");
- get_device_name(optind, argc, argv);
-
- rc = dasd_get_info(g.dev_node, &g.dasd_info);
- if (rc != 0)
- error("the ioctl call to retrieve device information failed: %s", strerror(rc));
-
- g.ese = dasd_sys_ese(g.dev_node);
- eval_format_mode();
+ while (optind < argc) {
+ get_device_name(optind, argc, argv);
+ strncpy(g.dev_path_array[numdev], g.dev_path, strlen(g.dev_path));
+ strncpy(g.dev_node_array[numdev], g.dev_node, strlen(g.dev_node));
- /* Either let the user specify the blksize or get it from the kernel */
- if (!g.blksize_specified) {
- if (!(mode == FULL ||
- g.dasd_info.format == DASD_FORMAT_NONE) || g.check)
- get_blocksize(&format_params.blksize);
- else
- format_params = ask_user_for_blksize(format_params);
+ optind++;
+ numdev++;
}
- if (g.keep_volser) {
- if (g.labelspec)
- error("The -k and -l options are mutually exclusive");
- if (!(format_params.intensity & DASD_FMT_INT_COMPAT))
- error("WARNING: VOLSER cannot be kept when using the ldl format!");
-
- if (dasdfmt_get_volser(old_volser) == 0)
- vtoc_volume_label_set_volser(&vlabel, old_volser);
- else
- error("VOLSER not found on device %s", g.dev_path);
- }
+ if (!numdev)
+ error("%s: No device specified!\n",
+ prog_name);
- check_disk();
+ if (numdev > 1 && g.labelspec)
+ error("Specifying a volser to be written doesn't make sense when formatting multiple DASD volumes.");
- if (check_param(str, ERR_LENGTH, &format_params) < 0)
- error("%s", str);
-
- set_geo(&cylinders, &heads);
- set_label(&vlabel, &format_params, cylinders);
-
- if (g.check)
- check_disk_format(cylinders, heads, &format_params);
- else
- do_format_dasd(&vlabel, &format_params, cylinders, heads);
+ for (i = 0; i < numdev; i++)
+ {
+ strncpy(g.dev_path, g.dev_path_array[i], strlen(g.dev_path_array[i])+1);
+ strncpy(g.dev_node, g.dev_node_array[i], strlen(g.dev_node_array[i])+1);
+ process_dasd(&vlabel, format_params);
+ }
free(g.dev_path);
free(g.dev_node);

View File

@ -0,0 +1,176 @@
From a61154fd93122f5a0f2b74f21c3ac29eb437f150 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 6 Oct 2017 09:39:36 +0200
Subject: [PATCH] dasdfmt: Format devices in parallel
Allow dasdfmt to run in parallel when several devices are specified.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
dasdfmt/dasdfmt.8 | 16 +++++++++++++-
dasdfmt/dasdfmt.c | 58 ++++++++++++++++++++++++++++++++++++++++++------------
2 files changed, 60 insertions(+), 14 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -7,7 +7,7 @@
dasdfmt \- formatting of DASD (ECKD) disk drives.
.SH SYNOPSIS
-\fBdasdfmt\fR [\-h] [\-t] [\-v] [\-y] [\-p] [\-P] [\-m \fIstep\fR]
+\fBdasdfmt\fR [\-h] [\-t] [\-v] [\-y] [\-p] [\-Q] [\-P] [\-m \fIstep\fR]
.br
[\-r \fIcylinder\fR] [\-b \fIblksize\fR] [\-l \fIvolser\fR] [\-d \fIlayout\fR]
.br
@@ -95,7 +95,7 @@
running in background or redirecting the output to a file.
.TP
-\fB\-P\fR or \fB\-\-percentage\fR
+\fB\-Q\fR or \fB\-\-percentage\fR
Print one line for each formatted cylinder showing the number of the
cylinder and percentage of formatting process.
Intended to be used by higher level interfaces.
@@ -164,6 +164,18 @@
.TP
\fB\-l\fR \fIvolser\fR or \fB\-\-label\fR=\fIvolser\fR
+\fB-P\fR \fInumdisks\fR or \fB--max_parallel\fR=\fInumdisks\fR
+Specify the number of disks to be formatted in parallel.
+\fInumdisks\fR specifies the number of formatting processed,
+independent on the overall number of disks to be formatted.
+The maximum value for \fInumdisks\fR is 512. Default is 1.
+.br
+Using this option can decrease overall processing time when formatting
+several disks. Please note that the I/O throughput will dramatically
+increase when using this option. Use with care.
+.br
+
+.TP
Specify the volume serial number or volume identifier to be written
to disk after formatting. If no label is specified, a sensible default
is used. \fIvolser\fR is interpreted as ASCII string and is automatically
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -13,6 +13,7 @@
#include <sys/sysmacros.h>
#include <sys/time.h>
#include <sys/utsname.h>
+#include <sys/wait.h>
#include "lib/dasd_base.h"
#include "lib/dasd_sys.h"
@@ -81,6 +82,7 @@
int mode_specified;
int ese;
int no_discard;
+ int procnum;
} g = {
.dasd_info = { 0 },
};
@@ -105,6 +107,11 @@
.desc = "Perform complete format check on device",
.flags = UTIL_OPT_FLAG_NOSHORT,
},
+ {
+ .option = { "max_parallel", required_argument, NULL, 'P' },
+ .desc = "Format devices in parallel",
+ .flags = UTIL_OPT_FLAG_NOLONG,
+ },
UTIL_OPT_SECTION("FORMAT OPTIONS"),
{
.option = { "blocksize", required_argument, NULL, 'b' },
@@ -162,7 +169,7 @@
.desc = "Show a progressbar",
},
{
- .option = { "percentage", no_argument, NULL, 'P' },
+ .option = { "percentage", no_argument, NULL, 'Q' },
.desc = "Show progress in percent",
},
UTIL_OPT_SECTION("MISC"),
@@ -311,7 +318,7 @@
}
if (g.print_hashmarks && (cyl / g.hashstep - hashcount) != 0) {
- printf("#");
+ printf("%d|", g.procnum);
fflush(stdout);
hashcount++;
}
@@ -1560,7 +1567,11 @@
char *reqsize_param_str = NULL;
char *hashstep_str = NULL;
- int rc, numdev = 0, i;
+ int rc, numdev = 0, numproc = 0, status;
+ int max_parallel =1 ;
+ int running = 0;
+ int chpid;
+ int tmp;
/* Establish a handler for interrupt signals. */
signal(SIGTERM, program_interrupt_signal);
@@ -1623,7 +1634,7 @@
g.print_hashmarks = 1;
}
break;
- case 'P':
+ case 'Q':
if (!(g.print_hashmarks || g.print_progressbar))
g.print_percentage = 1;
break;
@@ -1682,6 +1693,9 @@
case OPT_NODISCARD:
g.no_discard = 1;
break;
+ case 'P':
+ max_parallel = atoi(optarg);
+ break;
case OPT_CHECK:
g.check = 1;
break;
@@ -1733,15 +1747,35 @@
if (numdev > 1 && g.labelspec)
error("Specifying a volser to be written doesn't make sense when formatting multiple DASD volumes.");
- for (i = 0; i < numdev; i++)
- {
- strncpy(g.dev_path, g.dev_path_array[i], strlen(g.dev_path_array[i])+1);
- strncpy(g.dev_node, g.dev_node_array[i], strlen(g.dev_node_array[i])+1);
- process_dasd(&vlabel, format_params);
+ for (numproc = 0; numproc < numdev; numproc++) {
+ chpid = fork();
+ if (chpid == -1 )
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "%s: Unable to create child process: %s\n",
+ prog_name, strerror(errno));
+ if (!chpid) {
+ g.procnum = numproc;
+ strncpy(g.dev_path, g.dev_path_array[numproc], strlen(g.dev_path_array[numproc])+1);
+ strncpy(g.dev_node, g.dev_node_array[numproc], strlen(g.dev_node_array[numproc])+1);
+ process_dasd(&vlabel, format_params);
+
+ free(g.dev_path);
+ free(g.dev_node);
+ exit(0);
+ } else {
+ running++;
+ if (running >= max_parallel) {
+ if (wait(&tmp) > 0 && WEXITSTATUS(tmp))
+ rc = WEXITSTATUS(tmp);
+ running--;
+ }
+ }
}
- free(g.dev_path);
- free(g.dev_node);
+ /* wait until all formatting children have finished */
+ while(wait(&status) > 0)
+ if (WEXITSTATUS(status))
+ rc = WEXITSTATUS(status);
- return 0;
+ return rc;
}

View File

@ -0,0 +1,196 @@
From eabcb26fa4a91d410a6f75a9915a9ebb9f702c6b Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 6 Oct 2017 09:55:40 +0200
Subject: [PATCH] dasdfmt: Implement '-Y/--yast_mode'
Implement an option '-Y' to suppress most output.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
dasdfmt/dasdfmt.8 | 7 ++++-
dasdfmt/dasdfmt.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 72 insertions(+), 8 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -7,7 +7,7 @@
dasdfmt \- formatting of DASD (ECKD) disk drives.
.SH SYNOPSIS
-\fBdasdfmt\fR [\-h] [\-t] [\-v] [\-y] [\-p] [\-Q] [\-P] [\-m \fIstep\fR]
+\fBdasdfmt\fR [\-h] [\-t] [\-v] [\-y] [\-p] [\-Q] [\-P] [\-Y] [\-m \fIstep\fR]
.br
[\-r \fIcylinder\fR] [\-b \fIblksize\fR] [\-l \fIvolser\fR] [\-d \fIlayout\fR]
.br
@@ -112,6 +112,11 @@
.br
.TP
+\fB-Y\fR or \fB--yast_mode\fR
+YaST mode; suppress most output.
+.br
+
+.TP
\fB\-M\fR \fImode\fR or \fB\-\-mode\fR=\fImode\fR
Specify the \fImode\fR to be used to format the device. Valid modes are:
.RS
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -83,6 +83,7 @@
int ese;
int no_discard;
int procnum;
+ int yast_mode;
} g = {
.dasd_info = { 0 },
};
@@ -172,6 +173,10 @@
.option = { "percentage", no_argument, NULL, 'Q' },
.desc = "Show progress in percent",
},
+ {
+ .option = { "yast_mode", no_argument, NULL, 'Y' },
+ .desc = "YaST mode",
+ },
UTIL_OPT_SECTION("MISC"),
{
.option = { "check_host_count", no_argument, NULL, 'C' },
@@ -318,7 +323,9 @@
}
if (g.print_hashmarks && (cyl / g.hashstep - hashcount) != 0) {
- printf("%d|", g.procnum);
+ if (g.yast_mode)
+ printf("%d|", g.procnum);
+ else printf("#");
fflush(stdout);
hashcount++;
}
@@ -392,7 +399,7 @@
unsigned int kl = 0;
int blksize = cdata->expect.blksize;
- if (g.print_progressbar || g.print_hashmarks)
+ if ((g.print_progressbar || g.print_hashmarks) && !g.yast_mode)
printf("\n");
/*
@@ -780,8 +787,9 @@
g.hashstep = 10;
}
- printf("Printing hashmark every %d cylinders.\n",
- g.hashstep);
+ if (!g.yast_mode)
+ printf("Printing hashmark every %d cylinders.\n",
+ g.hashstep);
}
}
@@ -1462,17 +1470,19 @@
break;
}
- printf("Finished formatting the %s device.\n", g.dev_path);
+ if (!g.yast_mode)
+ printf("Finished formatting the %s device.\n", g.dev_path);
if (!(g.writenolabel || mode == EXPAND))
dasdfmt_write_labels(vlabel, cylinders, heads);
- printf("Rereading the partition table for %s... ", g.dev_path);
+ if (!g.yast_mode)
+ printf("Rereading the partition table for %s... ", g.dev_path);
err = dasd_reread_partition_table(g.dev_node, 5);
if (err != 0) {
ERRMSG("%s: error during rereading the partition "
"table: %s.\n", prog_name, strerror(err));
- } else {
+ } else if (!g.yast_mode) {
printf("ok\n");
}
}
@@ -1548,6 +1558,7 @@
error("%s", str);
set_geo(&cylinders, &heads);
+
set_label(&vlabel, &format_params, cylinders);
if (g.check)
@@ -1557,6 +1568,29 @@
}
+static void yast_print_cylinfo(const char *dev_filename)
+{
+ unsigned int cylinders = -1u;
+ int fd;
+ dasd_information2_t dasd_info;
+ struct dasd_eckd_characteristics *characteristics;
+
+ fd = open(dev_filename, O_RDONLY);
+ if ((fd != -1) && ( ! ioctl(fd, BIODASDINFO2, &dasd_info))) {
+
+ characteristics = (struct dasd_eckd_characteristics *) &dasd_info.characteristics;
+ if (characteristics->no_cyl == LV_COMPAT_CYL && characteristics->long_no_cyl)
+ cylinders = characteristics->long_no_cyl;
+ else
+ cylinders = characteristics->no_cyl;
+ }
+
+ if (fd != -1)
+ close(fd);
+ printf("%u\n", cylinders);
+ fflush(stdout);
+}
+
int main(int argc, char *argv[])
{
volume_label_t vlabel;
@@ -1693,6 +1727,10 @@
case OPT_NODISCARD:
g.no_discard = 1;
break;
+ case 'Y':
+ /* YaST mode */
+ g.yast_mode = 1;
+ break;
case 'P':
max_parallel = atoi(optarg);
break;
@@ -1728,6 +1766,21 @@
reqsize = DEFAULT_REQUESTSIZE;
}
+/* If -Y (YaST mode) was specified by the caller, then we need to suppress
+ * most of all the other output that might be generated. But, we _do_ want
+ * hashmarks printed so that YaST can track what's going on. If it wasn't
+ * specified on the command line, set it to a default of 10 cylinders.
+ */
+ if (g.yast_mode) {
+ g.verbosity = 0;
+ g.print_progressbar = 0;
+ g.print_percentage = 0;
+ if (! g.print_hashmarks) {
+ g.print_hashmarks = 1;
+ hashstep_str = "10";
+ }
+ }
+
if (g.print_hashmarks)
PARSE_PARAM_INTO(g.hashstep, hashstep_str, 10, "hashstep");
@@ -1747,6 +1800,12 @@
if (numdev > 1 && g.labelspec)
error("Specifying a volser to be written doesn't make sense when formatting multiple DASD volumes.");
+ if (g.yast_mode) {
+ for (numproc = 0; numproc < numdev; numproc++)
+ yast_print_cylinfo(g.dev_path_array[numproc]);
+
+ }
+
for (numproc = 0; numproc < numdev; numproc++) {
chpid = fork();
if (chpid == -1 )

View File

@ -0,0 +1,62 @@
From 8f05578d90df49dce6e13ee850fdc8bab84916ba Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 6 Oct 2017 12:23:32 +0200
Subject: [PATCH] dasdfmt: Implement '-f' for backwards compability
YaST is calling dasdfmt with '-f device', which used to be the old
calling convention. So to not keel over when used with an older
version of YaST we should accept this option, too.
Signed-off-by: Hannes Reinecke <hare@suse.com>
---
dasdfmt/dasdfmt.8 | 5 ++++-
dasdfmt/dasdfmt.c | 10 ++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -11,7 +11,7 @@
.br
[\-r \fIcylinder\fR] [\-b \fIblksize\fR] [\-l \fIvolser\fR] [\-d \fIlayout\fR]
.br
- [\-L] [\-V] [\-F] [\-k] [\-C] [\-M \fImode\fR] \fIdevice\fR [\fIdevice\fR]
+ [\-L] [\-V] [\-F] [\-k] [\-C] [\-M \fImode\fR] [-f \fIdevice\fR] [\fIdevice\fR]
.SH DESCRIPTION
\fBdasdfmt\fR formats one or several DASD (ECKD) disk drive(s) to prepare them
@@ -39,6 +39,9 @@
.TP
\fB\-v\fR
Increases verbosity.
+.TP
+\fB-f\fR \fIdevice\fR or \fB--device\fR=\fIdevice\fR
+Specify device to format. For backwards compability only.
.TP
\fB\-y\fR
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -113,6 +113,10 @@
.desc = "Format devices in parallel",
.flags = UTIL_OPT_FLAG_NOLONG,
},
+ {
+ .option = { "device", required_argument, NULL, 'f' },
+ .desc = "Specify device to format",
+ },
UTIL_OPT_SECTION("FORMAT OPTIONS"),
{
.option = { "blocksize", required_argument, NULL, 'b' },
@@ -1649,6 +1653,12 @@
}
g.layout_specified = 1;
break;
+ case 'f':
+ get_device_name(optind-1, argc, argv);
+ strncpy(g.dev_path_array[numdev], g.dev_path, strlen(g.dev_path));
+ strncpy(g.dev_node_array[numdev], g.dev_node, strlen(g.dev_node));
+ numdev++;
+ break;
case 'y':
g.withoutprompt = 1;
break;

View File

@ -0,0 +1,56 @@
From 943e577440d74ad7f8787af2590c8ab4579a459b Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Thu, 5 Nov 2015 10:57:38 +0100
Subject: [PATCH] dasdfmt: retry BIODASDINFO if device is busy
Modern udev have the wonderful 'feature' to sending a 'change'
event whenever a device opened with O_RDWR is closed again.
The reasoning is that the said program _might_ have changed
the partition table and hence we _might_ have missed a partition
update.
But in doing so it not only generated tons of pointless events
but also confused the hell out of other programs.
Idiots.
References: bsc#937340
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
dasdfmt/dasdfmt.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -621,7 +621,7 @@
*/
static void check_disk(void)
{
- int err;
+ int err, index = 0 ;
bool ro;
err = dasd_is_ro(g.dev_node, &ro);
@@ -631,6 +631,23 @@
if (ro)
error("Disk %s is read only!", g.dev_path);
if (!g.force) {
+ /*
+ * udev strikes again.
+ * Modern udev will issue a 'change' event whenever
+ * a device opened with O_RDWR is closed again.
+ * On the grounds that program _might_ have changed
+ * the partition table.
+ * And confusing the hell out ouf anyone else.
+ * Bah.
+ */
+ for ( index = 0 ; index < 6 ; index++ ) {
+ if (g.dasd_info.open_count > 1) {
+ dasd_get_info(g.dev_node, &g.dasd_info);
+ sleep(1);
+ }
+ else break;
+
+ }
if (g.dasd_info.open_count > 1)
error("Disk %s is in use!", g.dev_path);
}

View File

@ -0,0 +1,286 @@
Index: s390-tools-service/rust/pv/src/verify.rs
===================================================================
--- s390-tools-service.orig/rust/pv/src/verify.rs
+++ s390-tools-service/rust/pv/src/verify.rs
@@ -3,10 +3,11 @@
// Copyright IBM Corp. 2023
use core::slice;
-use log::debug;
+use log::{debug, trace};
+use openssl::error::ErrorStack;
use openssl::stack::Stack;
use openssl::x509::store::X509Store;
-use openssl::x509::{CrlStatus, X509Ref, X509StoreContext, X509};
+use openssl::x509::{CrlStatus, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef, X509};
use openssl_extensions::crl::StackableX509Crl;
use openssl_extensions::crl::X509StoreContextExtension;
@@ -82,8 +83,8 @@ impl HkdVerifier for CertVerifier {
if verified_crls.is_empty() {
bail_hkd_verify!(NoCrl);
}
- for crl in &verified_crls {
- match crl.get_by_cert(&hkd.to_owned()) {
+ for crl in verified_crls {
+ match crl.get_by_serial(hkd.serial_number()) {
CrlStatus::NotRevoked => (),
_ => bail_hkd_verify!(HdkRevoked),
}
@@ -94,21 +95,54 @@ impl HkdVerifier for CertVerifier {
}
impl CertVerifier {
+ fn quirk_crls(
+ ctx: &mut X509StoreContextRef,
+ subject: &X509NameRef,
+ ) -> Result<Stack<StackableX509Crl>, ErrorStack> {
+ match ctx.crls(subject) {
+ Ok(ret) if !ret.is_empty() => return Ok(ret),
+ _ => (),
+ }
+
+ // Armonk/Poughkeepsie fixup
+ trace!("quirk_crls: Try Locality");
+ if let Some(locality_subject) = helper::armonk_locality_fixup(subject) {
+ match ctx.crls(&locality_subject) {
+ Ok(ret) if !ret.is_empty() => return Ok(ret),
+ _ => (),
+ }
+
+ // reorder
+ trace!("quirk_crls: Try Locality+Reorder");
+ if let Ok(locality_ordered_subject) = helper::reorder_x509_names(&locality_subject) {
+ match ctx.crls(&locality_ordered_subject) {
+ Ok(ret) if !ret.is_empty() => return Ok(ret),
+ _ => (),
+ }
+ }
+ }
+
+ // reorder unchanged loaciliy subject
+ trace!("quirk_crls: Try Reorder");
+ if let Ok(ordered_subject) = helper::reorder_x509_names(subject) {
+ match ctx.crls(&ordered_subject) {
+ Ok(ret) if !ret.is_empty() => return Ok(ret),
+ _ => (),
+ }
+ }
+ // nothing found, return empty stack
+ Stack::new()
+ }
+
///Download the CLRs that a HKD refers to.
pub fn hkd_crls(&self, hkd: &X509Ref) -> Result<Stack<StackableX509Crl>> {
let mut ctx = X509StoreContext::new()?;
// Unfortunately we cannot use a dedicated function here and have to use a closure (E0434)
// Otherwise, we cannot refer to self
+ // Search for local CRLs
let mut crls = ctx.init_opt(&self.store, None, None, |ctx| {
let subject = self.ibm_z_sign_key.subject_name();
- match ctx.crls(subject) {
- Ok(crls) => Ok(crls),
- _ => {
- // reorder the name and try again
- let broken_subj = helper::reorder_x509_names(subject)?;
- ctx.crls(&broken_subj).or_else(helper::stack_err_hlp)
- }
- }
+ Self::quirk_crls(ctx, subject)
})?;
if !self.offline {
Index: s390-tools-service/rust/pv/src/verify/helper.rs
===================================================================
--- s390-tools-service.orig/rust/pv/src/verify/helper.rs
+++ s390-tools-service/rust/pv/src/verify/helper.rs
@@ -13,7 +13,7 @@ use openssl::{
error::ErrorStack,
nid::Nid,
ssl::SslFiletype,
- stack::{Stack, Stackable},
+ stack::Stack,
x509::{
store::{File, X509Lookup, X509StoreBuilder, X509StoreBuilderRef, X509StoreRef},
verify::{X509VerifyFlags, X509VerifyParam},
@@ -25,6 +25,7 @@ use openssl_extensions::{
akid::{AkidCheckResult, AkidExtension},
crl::X509StoreExtension,
};
+use std::str::from_utf8;
use std::{cmp::Ordering, ffi::c_int, time::Duration, usize};
/// Minimum security level for the keys/certificates used to establish a chain of
@@ -39,7 +40,6 @@ const SECURITY_CHAIN_MAX_LEN: c_int = 2;
/// verifies that the HKD
/// * has enough security bits
/// * is inside its validity period
-/// * issuer name is the subject name of the [`sign_key`]
/// * the Authority Key ID matches the Signing Key ID of the [`sign_key`]
pub fn verify_hkd_options(hkd: &X509Ref, sign_key: &X509Ref) -> Result<()> {
let hk_pkey = hkd.public_key()?;
@@ -53,9 +53,6 @@ pub fn verify_hkd_options(hkd: &X509Ref,
// verify that the hkd is still valid
check_validity_period(hkd.not_before(), hkd.not_after())?;
- // check if hkd.issuer_name == issuer.subject
- check_x509_name_equal(sign_key.subject_name(), hkd.issuer_name())?;
-
// verify that the AKID of the hkd matches the SKID of the issuer
if let Some(akid) = hkd.akid() {
if akid.check(sign_key) != AkidCheckResult::OK {
@@ -75,9 +72,6 @@ pub fn verify_crl(crl: &X509CrlRef, issu
return None;
}
}
-
- check_x509_name_equal(crl.issuer_name(), issuer.subject_name()).ok()?;
-
match crl.verify(issuer.public_key().ok()?.as_ref()).ok()? {
true => Some(()),
false => None,
@@ -207,7 +201,8 @@ pub fn download_crls_into_store(store: &
//Asn1StringRef::as_slice aka ASN1_STRING_get0_data gives a string without \0 delimiter
const IBM_Z_COMMON_NAME: &[u8; 43usize] = b"International Business Machines Corporation";
const IBM_Z_COUNTRY_NAME: &[u8; 2usize] = b"US";
-const IBM_Z_LOCALITY_NAME: &[u8; 12usize] = b"Poughkeepsie";
+const IBM_Z_LOCALITY_NAME_POUGHKEEPSIE: &[u8; 12usize] = b"Poughkeepsie";
+const IBM_Z_LOCALITY_NAME_ARMONK: &[u8; 6usize] = b"Armonk";
const IBM_Z_ORGANIZATIONAL_UNIT_NAME_SUFFIX: &str = "Key Signing Service";
const IBM_Z_ORGANIZATION_NAME: &[u8; 43usize] = b"International Business Machines Corporation";
const IBM_Z_STATE: &[u8; 8usize] = b"New York";
@@ -226,7 +221,8 @@ fn is_ibm_signing_cert(cert: &X509) -> b
if subj.entries().count() != IMB_Z_ENTRY_COUNT
|| !name_data_eq(subj, Nid::COUNTRYNAME, IBM_Z_COUNTRY_NAME)
|| !name_data_eq(subj, Nid::STATEORPROVINCENAME, IBM_Z_STATE)
- || !name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME)
+ || !(name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_POUGHKEEPSIE)
+ || name_data_eq(subj, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_ARMONK))
|| !name_data_eq(subj, Nid::ORGANIZATIONNAME, IBM_Z_ORGANIZATION_NAME)
|| !name_data_eq(subj, Nid::COMMONNAME, IBM_Z_COMMON_NAME)
{
@@ -367,24 +363,6 @@ fn check_validity_period(not_before: &As
}
}
-fn check_x509_name_equal(lhs: &X509NameRef, rhs: &X509NameRef) -> Result<()> {
- if lhs.entries().count() != rhs.entries().count() {
- bail_hkd_verify!(IssuerMismatch);
- }
-
- for l in lhs.entries() {
- // search for the matching value in the rhs names
- // found none? -> names are not equal
- if !rhs
- .entries()
- .any(|r| l.data().as_slice() == r.data().as_slice())
- {
- bail_hkd_verify!(IssuerMismatch);
- }
- }
- Ok(())
-}
-
const NIDS_CORRECT_ORDER: [Nid; 6] = [
Nid::COUNTRYNAME,
Nid::ORGANIZATIONNAME,
@@ -407,13 +385,28 @@ pub fn reorder_x509_names(subject: &X509
Ok(correct_subj.build())
}
-pub fn stack_err_hlp<T: Stackable>(
- e: ErrorStack,
-) -> std::result::Result<Stack<T>, openssl::error::ErrorStack> {
- match e.errors().len() {
- 0 => Stack::<T>::new(),
- _ => Err(e),
+/**
+* Workaround for potential locality mismatches between CRLs and Certs
+* # Return
+* fixed subject or none if locality was not Armonk or any OpenSSL error
+*/
+pub fn armonk_locality_fixup(subject: &X509NameRef) -> Option<X509Name> {
+ if !name_data_eq(subject, Nid::LOCALITYNAME, IBM_Z_LOCALITY_NAME_ARMONK) {
+ return None;
+ }
+
+ let mut ret = X509Name::builder().ok()?;
+ for entry in subject.entries() {
+ match entry.object().nid() {
+ nid @ Nid::LOCALITYNAME => ret
+ .append_entry_by_nid(nid, from_utf8(IBM_Z_LOCALITY_NAME_POUGHKEEPSIE).ok()?)
+ .ok()?,
+ _ => {
+ ret.append_entry(entry).ok()?;
+ }
+ }
}
+ Some(ret.build())
}
#[cfg(test)]
@@ -451,20 +444,6 @@ mod test {
));
}
- #[test]
- fn x509_name_equal() {
- let sign_crt = load_gen_cert("ibm.crt");
- let hkd = load_gen_cert("host.crt");
- let other = load_gen_cert("inter_ca.crt");
-
- assert!(super::check_x509_name_equal(sign_crt.subject_name(), hkd.issuer_name()).is_ok(),);
-
- assert!(matches!(
- super::check_x509_name_equal(other.subject_name(), hkd.subject_name()),
- Err(Error::HkdVerify(IssuerMismatch))
- ));
- }
-
#[test]
fn is_ibm_z_sign_key() {
let ibm_crt = load_gen_cert("ibm.crt");
Index: s390-tools-service/rust/pv/src/verify/test.rs
===================================================================
--- s390-tools-service.orig/rust/pv/src/verify/test.rs
+++ s390-tools-service/rust/pv/src/verify/test.rs
@@ -84,7 +84,6 @@ fn verify_online() {
let inter_crt = get_cert_asset_path_string("inter_ca.crt");
let ibm_crt = get_cert_asset_path_string("ibm.crt");
let hkd_revoked = load_gen_cert("host_rev.crt");
- let hkd_inv = load_gen_cert("host_invalid_signing_key.crt");
let hkd_exp = load_gen_cert("host_crt_expired.crt");
let hkd = load_gen_cert("host.crt");
@@ -112,11 +111,6 @@ fn verify_online() {
));
assert!(matches!(
- verifier.verify(&hkd_inv),
- Err(Error::HkdVerify(IssuerMismatch))
- ));
-
- assert!(matches!(
verifier.verify(&hkd_exp),
Err(Error::HkdVerify(AfterValidity))
));
@@ -130,7 +124,6 @@ fn verify_offline() {
let ibm_crt = get_cert_asset_path_string("ibm.crt");
let ibm_crl = get_cert_asset_path_string("ibm.crl");
let hkd_revoked = load_gen_cert("host_rev.crt");
- let hkd_inv = load_gen_cert("host_invalid_signing_key.crt");
let hkd_exp = load_gen_cert("host_crt_expired.crt");
let hkd = load_gen_cert("host.crt");
@@ -149,11 +142,6 @@ fn verify_offline() {
));
assert!(matches!(
- verifier.verify(&hkd_inv),
- Err(Error::HkdVerify(IssuerMismatch))
- ));
-
- assert!(matches!(
verifier.verify(&hkd_exp),
Err(Error::HkdVerify(AfterValidity))
));

View File

@ -0,0 +1,17 @@
---
common.mak | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/common.mak
+++ b/common.mak
@@ -338,8 +338,8 @@
LDFLAGS CPPFLAGS ALL_CFLAGS ALL_CXXFLAGS ALL_LDFLAGS ALL_CPPFLAGS
ifneq ($(shell $(CC_SILENT) -dumpspecs 2>/dev/null | grep -e '[^f]no-pie'),)
- NO_PIE_CFLAGS := -fno-pie
- NO_PIE_LDFLAGS := -no-pie
+ NO_PIE_CFLAGS :=
+ NO_PIE_LDFLAGS :=
else
NO_PIE_CFLAGS :=
NO_PIE_LDFLAGS :=

View File

@ -0,0 +1,97 @@
From 3ea6d6dfd2eb120ffee4c44ff51b7e9e7a9097a6 Mon Sep 17 00:00:00 2001
From: Thomas Blume <Thomas.Blume@suse.com>
Date: Thu, 28 Mar 2024 13:32:46 +0100
Subject: [PATCH] parse ipl device for activation
ported from dracut modules
---
zdev/dracut/95zdev/parse-dasd.sh | 15 ++++++++---
zdev/dracut/95zdev/parse-zfcp.sh | 46 +++++++++++++++++++-------------
2 files changed, 39 insertions(+), 22 deletions(-)
diff --git a/zdev/dracut/95zdev/parse-dasd.sh b/zdev/dracut/95zdev/parse-dasd.sh
index a97801f..eb2fa64 100644
--- a/zdev/dracut/95zdev/parse-dasd.sh
+++ b/zdev/dracut/95zdev/parse-dasd.sh
@@ -27,9 +27,18 @@ zdev_vinfo() {
zdev_parse_rd_dasd() {
local _zdev_dasd _zdev_dasd_list
- for _zdev_dasd in $(getargs rd.dasd -d 'rd_DASD='); do
- _zdev_dasd_list="${_zdev_dasd_list:+${_zdev_dasd_list},}$_zdev_dasd"
- done
+ # autodetect active bootdev from zipl device
+ if ! getargbool 0 'rd.dasd' \
+ && [[ -f /sys/firmware/ipl/ipl_type ]] \
+ && [[ $(< /sys/firmware/ipl/ipl_type) == "ccw" ]]; then
+ read -r _ccw < /sys/firmware/ipl/device
+
+ chzdev --offline --existing --enable --active dasd "$_ccw"
+ else
+ for _zdev_dasd in $(getargs rd.dasd -d 'rd_DASD='); do
+ _zdev_dasd_list="${_zdev_dasd_list:+${_zdev_dasd_list},}$_zdev_dasd"
+ done
+ fi
echo "$_zdev_dasd_list"
}
diff --git a/zdev/dracut/95zdev/parse-zfcp.sh b/zdev/dracut/95zdev/parse-zfcp.sh
index 715aa00..6279beb 100644
--- a/zdev/dracut/95zdev/parse-zfcp.sh
+++ b/zdev/dracut/95zdev/parse-zfcp.sh
@@ -12,25 +12,33 @@
zdev_zfcp_base_args="--no-settle --yes --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"
- echo "rd.zfcp ${zdev_zfcp_arg} :" | zdev_vinfo
- if [ "$#" -eq 1 ]; then
+# autodetect active bootdev from zipl device
+if ! getargbool 0 'rd.zfcp' \
+ && [[ -f /sys/firmware/ipl/ipl_type ]] \
+ && [[ $(< /sys/firmware/ipl/ipl_type) == "fcp" ]]; then
+ chzdev --offline --existing --enable --active zfcp-host 2>&1 | zdev_vinfo
+else
+ 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
- chzdev --enable --persistent $zdev_zfcp_base_args \
- zfcp-host "$args" 2>&1 | zdev_vinfo
- else
- # shellcheck disable=SC2086
- chzdev --enable --persistent $zdev_zfcp_base_args \
- zfcp-lun "$args" 2>&1 | zdev_vinfo
- fi
- )
-done
+ set -- $zdev_zfcp_arg
+ IFS=":" args="$*"
+ IFS="$IFS_SAVED"
+ echo "rd.zfcp ${zdev_zfcp_arg} :" | zdev_vinfo
+ if [ "$#" -eq 1 ]; then
+ # shellcheck disable=SC2086
+ chzdev --enable --persistent $zdev_zfcp_base_args \
+ zfcp-host "$args" 2>&1 | zdev_vinfo
+ else
+ # shellcheck disable=SC2086
+ chzdev --enable --persistent $zdev_zfcp_base_args \
+ zfcp-lun "$args" 2>&1 | zdev_vinfo
+ fi
+ )
+ done
+fi
+
unset zdev_zfcp_arg
unset zdev_zfcp_base_args
--
2.44.0

View File

@ -0,0 +1,304 @@
Index: s390-tools-service/genprotimg/src/include/pv_crypto_def.h
===================================================================
--- s390-tools-service.orig/genprotimg/src/include/pv_crypto_def.h
+++ s390-tools-service/genprotimg/src/include/pv_crypto_def.h
@@ -17,7 +17,8 @@
/* IBM signing key subject */
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
-#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
+#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie"
+#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk"
#define PV_IBM_Z_SUBJECT_ORGANIZATIONONAL_UNIT_NAME_SUFFIX "Key Signing Service"
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_STATE "New York"
Index: s390-tools-service/genprotimg/src/utils/crypto.c
===================================================================
--- s390-tools-service.orig/genprotimg/src/utils/crypto.c
+++ s390-tools-service/genprotimg/src/utils/crypto.c
@@ -664,62 +664,9 @@ static gboolean x509_name_data_by_nid_eq
return memcmp(data, y, data_len) == 0;
}
-static gboolean own_X509_NAME_ENTRY_equal(const X509_NAME_ENTRY *x,
- const X509_NAME_ENTRY *y)
-{
- const ASN1_OBJECT *x_obj = X509_NAME_ENTRY_get_object(x);
- const ASN1_STRING *x_data = X509_NAME_ENTRY_get_data(x);
- const ASN1_OBJECT *y_obj = X509_NAME_ENTRY_get_object(y);
- const ASN1_STRING *y_data = X509_NAME_ENTRY_get_data(y);
- gint x_len = ASN1_STRING_length(x_data);
- gint y_len = ASN1_STRING_length(y_data);
-
- if (x_len < 0 || x_len != y_len)
- return FALSE;
-
- /* ASN1_STRING_cmp(x_data, y_data) == 0 doesn't work because it also
- * compares the type, which is sometimes different.
- */
- return OBJ_cmp(x_obj, y_obj) == 0 &&
- memcmp(ASN1_STRING_get0_data(x_data),
- ASN1_STRING_get0_data(y_data),
- (unsigned long)x_len) == 0;
-}
-
-static gboolean own_X509_NAME_equal(const X509_NAME *x, const X509_NAME *y)
-{
- gint x_count = X509_NAME_entry_count(x);
- gint y_count = X509_NAME_entry_count(y);
-
- if (x != y && (!x || !y))
- return FALSE;
-
- if (x_count != y_count)
- return FALSE;
-
- for (gint i = 0; i < x_count; i++) {
- const X509_NAME_ENTRY *entry_i = X509_NAME_get_entry(x, i);
- gboolean entry_found = FALSE;
-
- for (gint j = 0; j < y_count; j++) {
- const X509_NAME_ENTRY *entry_j =
- X509_NAME_get_entry(y, j);
-
- if (own_X509_NAME_ENTRY_equal(entry_i, entry_j)) {
- entry_found = TRUE;
- break;
- }
- }
-
- if (!entry_found)
- return FALSE;
- }
- return TRUE;
-}
-
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
* must check that the subject is equal to: 'C = US, ST = New York, L =
- * Poughkeepsie, O = International Business Machines Corporation, CN =
+ * Poughkeepsie or Armonk, O = International Business Machines Corporation, CN =
* International Business Machines Corporation' and the organization unit (OUT)
* must end with the suffix ' Key Signing Service'.
*/
@@ -743,8 +690,10 @@ static gboolean has_ibm_signing_subject(
PV_IBM_Z_SUBJECT_STATE))
return FALSE;
- if (!x509_name_data_by_nid_equal(subject, NID_localityName,
- PV_IBM_Z_SUBJECT_LOCALITY_NAME))
+ if (!(x509_name_data_by_nid_equal(subject, NID_localityName,
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) ||
+ x509_name_data_by_nid_equal(subject, NID_localityName,
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)))
return FALSE;
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
@@ -806,6 +755,39 @@ static X509_NAME *x509_name_reorder_attr
return g_steal_pointer(&ret);
}
+/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return
+ * `NULL`.
+ */
+static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name)
+{
+ g_autoptr(X509_NAME) ret = NULL;
+ int pos;
+
+ /* Check if ``L=Armonk`` */
+ if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName,
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))
+ return NULL;
+
+ ret = X509_NAME_dup(name);
+ if (!ret)
+ g_abort();
+
+ pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1);
+ if (pos == -1)
+ return NULL;
+
+ X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos));
+
+ /* Create a new name entry at the same position as before */
+ if (X509_NAME_add_entry_by_NID(
+ ret, NID_localityName, MBSTRING_UTF8,
+ (const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE,
+ sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1)
+ return NULL;
+
+ return g_steal_pointer(&ret);
+}
+
/* In RFC 5280 the attributes of a (subject/issuer) name is not mandatory
* ordered. The problem is that our certificates are not consistent in the order
* (see https://tools.ietf.org/html/rfc5280#section-4.1.2.4 for details).
@@ -828,24 +810,10 @@ X509_NAME *c2b_name(const X509_NAME *nam
return X509_NAME_dup((X509_NAME *)name);
}
-/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */
+/* Verify that SKID(issuer) == AKID(crl) if available */
static gint check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **err)
{
- const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl);
- const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
- AUTHORITY_KEYID *akid = NULL;
-
- if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) {
- g_autofree char *issuer_subject_str = X509_NAME_oneline(issuer_subject,
- NULL, 0);
- g_autofree char *crl_issuer_str = X509_NAME_oneline(crl_issuer, NULL, 0);
-
- g_set_error(err, PV_CRYPTO_ERROR,
- PV_CRYPTO_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
- _("issuer mismatch:\n%s\n%s"),
- issuer_subject_str, crl_issuer_str);
- return -1;
- }
+ g_autoptr(AUTHORITY_KEYID) akid = NULL;
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
@@ -881,7 +849,6 @@ gint check_crl_valid_for_cert(X509_CRL *
return -1;
}
- /* check that the @crl issuer matches with the subject name of @cert*/
if (check_crl_issuer(crl, cert, err) < 0)
return -1;
@@ -910,6 +877,60 @@ gint check_crl_valid_for_cert(X509_CRL *
return 0;
}
+/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL)
+ * issues.
+ */
+static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx,
+ const X509_NAME *subject, GError **err)
+{
+ g_autoptr(X509_NAME) fixed_subject = NULL;
+ g_autoptr(STACK_OF_X509_CRL) ret = NULL;
+
+ ret = Pv_X509_STORE_CTX_get1_crls(ctx, subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+
+ /* Workaround to fix the mismatch between issuer name of the * IBM
+ * signing CRLs and the IBM signing key subject name. Locality name has
+ * changed from Poughkeepsie to Armonk.
+ */
+ fixed_subject = x509_armonk_locality_fixup(subject);
+ /* Was the locality replaced? */
+ if (fixed_subject) {
+ X509_NAME *tmp;
+
+ sk_X509_CRL_free(ret);
+ ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+
+ /* Workaround to fix the ordering mismatch between issuer name
+ * of the IBM signing CRLs and the IBM signing key subject name.
+ */
+ tmp = fixed_subject;
+ fixed_subject = c2b_name(fixed_subject);
+ X509_NAME_free(tmp);
+ sk_X509_CRL_free(ret);
+ ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+ X509_NAME_free(fixed_subject);
+ fixed_subject = NULL;
+ }
+
+ /* Workaround to fix the ordering mismatch between issuer name of the
+ * IBM signing CRLs and the IBM signing key subject name.
+ */
+ fixed_subject = c2b_name(subject);
+ sk_X509_CRL_free(ret);
+ ret = Pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+
+ g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL, _("no CRL found"));
+ return NULL;
+}
+
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
* valid CRL was found NULL is returned.
*/
@@ -927,20 +948,9 @@ STACK_OF_X509_CRL *store_ctx_find_valid_
return NULL;
}
- ret = X509_STORE_CTX_get1_crls(ctx, subject);
- if (!ret) {
- /* Workaround to fix the mismatch between issuer name of the
- * IBM Z signing CRLs and the IBM Z signing key subject name.
- */
- g_autoptr(X509_NAME) broken_subject = c2b_name(subject);
-
- ret = X509_STORE_CTX_get1_crls(ctx, broken_subject);
- if (!ret) {
- g_set_error(err, PV_CRYPTO_ERROR, PV_CRYPTO_ERROR_NO_CRL,
- _("no CRL found"));
- return NULL;
- }
- }
+ ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, err);
+ if (!ret)
+ return NULL;
/* Filter out non-valid CRLs for @cert */
for (gint i = 0; i < sk_X509_CRL_num(ret); i++) {
@@ -1328,32 +1338,14 @@ gint check_chain_parameters(const STACK_
/* It's almost the same as X509_check_issed from OpenSSL does except that we
* don't check the key usage of the potential issuer. This means we check:
- * 1. issuer_name(cert) == subject_name(issuer)
- * 2. Check whether the akid(cert) (if available) matches the issuer skid
- * 3. Check that the cert algrithm matches the subject algorithm
- * 4. Verify the signature of certificate @cert is using the public key of
+ * 1. Check whether the akid(cert) (if available) matches the issuer skid
+ * 2. Check that the cert algrithm matches the subject algorithm
+ * 3. Verify the signature of certificate @cert is using the public key of
* @issuer.
*/
static gint check_host_key_issued(X509 *cert, X509 *issuer, GError **err)
{
- const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
- const X509_NAME *cert_issuer = X509_get_issuer_name(cert);
- AUTHORITY_KEYID *akid = NULL;
-
- /* We cannot use X509_NAME_cmp() because it considers the order of the
- * X509_NAME_Entries.
- */
- if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) {
- g_autofree char *issuer_subject_str =
- X509_NAME_oneline(issuer_subject, NULL, 0);
- g_autofree char *cert_issuer_str =
- X509_NAME_oneline(cert_issuer, NULL, 0);
- g_set_error(err, PV_CRYPTO_ERROR,
- PV_CRYPTO_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
- _("Subject issuer mismatch:\n'%s'\n'%s'"),
- issuer_subject_str, cert_issuer_str);
- return -1;
- }
+ g_autoptr(AUTHORITY_KEYID) akid = NULL;
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
Index: s390-tools-service/genprotimg/src/utils/crypto.h
===================================================================
--- s390-tools-service.orig/genprotimg/src/utils/crypto.h
+++ s390-tools-service/genprotimg/src/utils/crypto.h
@@ -75,6 +75,7 @@ void x509_pair_free(x509_pair *pair);
/* Register auto cleanup functions */
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_INTEGER, ASN1_INTEGER_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(ASN1_OCTET_STRING, ASN1_OCTET_STRING_free)
+WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(AUTHORITY_KEYID, AUTHORITY_KEYID_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIGNUM, BN_free)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BIO, BIO_free_all)
WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(BN_CTX, BN_CTX_free)

View File

@ -0,0 +1,224 @@
Index: s390-tools-service/include/libpv/cert.h
===================================================================
--- s390-tools-service.orig/include/libpv/cert.h
+++ s390-tools-service/include/libpv/cert.h
@@ -16,7 +16,8 @@
#define PV_IBM_Z_SUBJECT_COMMON_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_COUNTRY_NAME "US"
-#define PV_IBM_Z_SUBJECT_LOCALITY_NAME "Poughkeepsie"
+#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE "Poughkeepsie"
+#define PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK "Armonk"
#define PV_IBM_Z_SUBJECT_ORGANIZATIONAL_UNIT_NAME_SUFFIX "Key Signing Service"
#define PV_IBM_Z_SUBJECT_ORGANIZATION_NAME "International Business Machines Corporation"
#define PV_IBM_Z_SUBJECT_STATE "New York"
Index: s390-tools-service/libpv/cert.c
===================================================================
--- s390-tools-service.orig/libpv/cert.c
+++ s390-tools-service/libpv/cert.c
@@ -857,7 +857,7 @@ static gboolean x509_name_data_by_nid_eq
/* Checks whether the subject of @cert is a IBM signing key subject. For this we
* must check that the subject is equal to: 'C = US, ST = New York, L =
- * Poughkeepsie, O = International Business Machines Corporation, CN =
+ * Poughkeepsie or Armonk, O = International Business Machines Corporation, CN =
* International Business Machines Corporation' and the organization unit (OUT)
* must end with the suffix ' Key Signing Service'.
*/
@@ -879,7 +879,10 @@ static gboolean has_ibm_signing_subject(
if (!x509_name_data_by_nid_equal(subject, NID_stateOrProvinceName, PV_IBM_Z_SUBJECT_STATE))
return FALSE;
- if (!x509_name_data_by_nid_equal(subject, NID_localityName, PV_IBM_Z_SUBJECT_LOCALITY_NAME))
+ if (!(x509_name_data_by_nid_equal(subject, NID_localityName,
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) ||
+ x509_name_data_by_nid_equal(subject, NID_localityName,
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK)))
return FALSE;
if (!x509_name_data_by_nid_equal(subject, NID_organizationName,
@@ -1085,10 +1088,9 @@ static int check_signature_algo_match(co
/* It's almost the same as X509_check_issed from OpenSSL does except that we
* don't check the key usage of the potential issuer. This means we check:
- * 1. issuer_name(cert) == subject_name(issuer)
- * 2. Check whether the akid(cert) (if available) matches the issuer skid
- * 3. Check that the cert algrithm matches the subject algorithm
- * 4. Verify the signature of certificate @cert is using the public key of
+ * 1. Check whether the akid(cert) (if available) matches the issuer skid
+ * 2. Check that the cert algrithm matches the subject algorithm
+ * 3. Verify the signature of certificate @cert is using the public key of
* @issuer.
*/
static int check_host_key_issued(X509 *cert, X509 *issuer, GError **error)
@@ -1097,19 +1099,6 @@ static int check_host_key_issued(X509 *c
const X509_NAME *cert_issuer = X509_get_issuer_name(cert);
g_autoptr(AUTHORITY_KEYID) akid = NULL;
- /* We cannot use X509_NAME_cmp() because it considers the order of the
- * X509_NAME_Entries.
- */
- if (!own_X509_NAME_equal(issuer_subject, cert_issuer)) {
- g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject);
- g_autofree char *cert_issuer_str = pv_X509_NAME_oneline(cert_issuer);
-
- g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CERT_SUBJECT_ISSUER_MISMATCH,
- _("Subject issuer mismatch:\n'%s'\n'%s'"), issuer_subject_str,
- cert_issuer_str);
- return -1;
- }
-
akid = X509_get_ext_d2i(cert, NID_authority_key_identifier, NULL, NULL);
if (akid && X509_check_akid(issuer, akid) != X509_V_OK) {
g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_SKID_AKID_MISMATCH,
@@ -1286,21 +1275,10 @@ int pv_verify_cert(X509_STORE_CTX *ctx,
return 0;
}
-/* Verify that: subject(issuer) == issuer(crl) and SKID(issuer) == AKID(crl) */
+/* Verify that SKID(issuer) == AKID(crl) */
static int check_crl_issuer(X509_CRL *crl, X509 *issuer, GError **error)
{
- const X509_NAME *crl_issuer = X509_CRL_get_issuer(crl);
- const X509_NAME *issuer_subject = X509_get_subject_name(issuer);
- AUTHORITY_KEYID *akid = NULL;
-
- if (!own_X509_NAME_equal(issuer_subject, crl_issuer)) {
- g_autofree char *issuer_subject_str = pv_X509_NAME_oneline(issuer_subject);
- g_autofree char *crl_issuer_str = pv_X509_NAME_oneline(crl_issuer);
-
- g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_CRL_SUBJECT_ISSUER_MISMATCH,
- _("issuer mismatch:\n%s\n%s"), issuer_subject_str, crl_issuer_str);
- return -1;
- }
+ g_autoptr(AUTHORITY_KEYID) akid = NULL;
/* If AKID(@crl) is specified it must match with SKID(@issuer) */
akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL);
@@ -1325,7 +1303,6 @@ int pv_verify_crl(X509_CRL *crl, X509 *c
return -1;
}
- /* check that the @crl issuer matches with the subject name of @cert*/
if (check_crl_issuer(crl, cert, error) < 0)
return -1;
@@ -1393,6 +1370,93 @@ int pv_check_chain_parameters(const STAC
return 0;
}
+/** Replace locality 'Armonk' with 'Pougkeepsie'. If Armonk was not set return
+ * `NULL`.
+ */
+static X509_NAME *x509_armonk_locality_fixup(const X509_NAME *name)
+{
+ g_autoptr(X509_NAME) ret = NULL;
+ int pos;
+
+ /* Check if ``L=Armonk`` */
+ if (!x509_name_data_by_nid_equal((X509_NAME *)name, NID_localityName,
+ PV_IBM_Z_SUBJECT_LOCALITY_NAME_ARMONK))
+ return NULL;
+
+ ret = X509_NAME_dup(name);
+ if (!ret)
+ g_abort();
+
+ pos = X509_NAME_get_index_by_NID(ret, NID_localityName, -1);
+ if (pos == -1)
+ return NULL;
+
+ X509_NAME_ENTRY_free(X509_NAME_delete_entry(ret, pos));
+
+ /* Create a new name entry at the same position as before */
+ if (X509_NAME_add_entry_by_NID(
+ ret, NID_localityName, MBSTRING_UTF8,
+ (const unsigned char *)&PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE,
+ sizeof(PV_IBM_Z_SUBJECT_LOCALITY_NAME_POUGHKEEPSIE) - 1, pos, 0) != 1)
+ return NULL;
+
+ return g_steal_pointer(&ret);
+}
+
+/* This function contains work-arounds for some known subject(CRT)<->issuer(CRL)
+ * issues.
+ */
+static STACK_OF_X509_CRL *quirk_X509_STORE_ctx_get1_crls(X509_STORE_CTX *ctx,
+ const X509_NAME *subject, GError **err)
+{
+ g_autoptr(X509_NAME) fixed_subject = NULL;
+ g_autoptr(STACK_OF_X509_CRL) ret = NULL;
+
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+
+ /* Workaround to fix the mismatch between issuer name of the * IBM
+ * signing CRLs and the IBM signing key subject name. Locality name has
+ * changed from Poughkeepsie to Armonk.
+ */
+ fixed_subject = x509_armonk_locality_fixup(subject);
+ /* Was the locality replaced? */
+ if (fixed_subject) {
+ X509_NAME *tmp;
+
+ sk_X509_CRL_free(ret);
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+
+ /* Workaround to fix the ordering mismatch between issuer name
+ * of the IBM signing CRLs and the IBM signing key subject name.
+ */
+ tmp = fixed_subject;
+ fixed_subject = pv_c2b_name(fixed_subject);
+ X509_NAME_free(tmp);
+ sk_X509_CRL_free(ret);
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+ X509_NAME_free(fixed_subject);
+ fixed_subject = NULL;
+ }
+
+ /* Workaround to fix the ordering mismatch between issuer name of the
+ * IBM signing CRLs and the IBM signing key subject name.
+ */
+ fixed_subject = pv_c2b_name(subject);
+ sk_X509_CRL_free(ret);
+ ret = pv_X509_STORE_CTX_get1_crls(ctx, fixed_subject);
+ if (ret && sk_X509_CRL_num(ret) > 0)
+ return g_steal_pointer(&ret);
+
+ g_set_error(err, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found"));
+ return NULL;
+}
+
/* Given a certificate @cert try to find valid revocation lists in @ctx. If no
* valid CRL was found NULL is returned.
*/
@@ -1412,21 +1476,9 @@ STACK_OF_X509_CRL *pv_store_ctx_find_val
return NULL;
}
- ret = pv_X509_STORE_CTX_get1_crls(ctx, subject);
- if (!ret) {
- /* Workaround to fix the mismatch between issuer name of the
- * IBM Z signing CRLs and the IBM Z signing key subject name.
- */
- g_autoptr(X509_NAME) broken_subject = pv_c2b_name(subject);
-
- ret = pv_X509_STORE_CTX_get1_crls(ctx, broken_subject);
- if (!ret) {
- g_set_error(error, PV_CERT_ERROR, PV_CERT_ERROR_NO_CRL, _("no CRL found"));
- g_info("ERROR: %s", (*error)->message);
- return NULL;
- }
- }
-
+ ret = quirk_X509_STORE_ctx_get1_crls(ctx, subject, error);
+ if (!ret)
+ return NULL;
/* Filter out non-valid CRLs for @cert */
for (int i = 0; i < sk_X509_CRL_num(ret); i++) {
X509_CRL *crl = sk_X509_CRL_value(ret, i);

View File

@ -0,0 +1,25 @@
Index: s390-tools-service/pvattest/src/argparse.c
===================================================================
--- s390-tools-service.orig/pvattest/src/argparse.c
+++ s390-tools-service/pvattest/src/argparse.c
@@ -190,13 +190,13 @@ static gboolean hex_str_toull(const char
}
/* NOTE REQUIRED */
-#define _entry_root_ca(__arg_data, __indent) \
- { \
- .long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
- .arg = G_OPTION_ARG_FILENAME_ARRAY, .arg_data = __arg_data, \
- .description = "Use FILE as the trusted root CA instead the\n" __indent \
- "root CAs that are installed on the system (optional).\n", \
- .arg_description = "FILE", \
+#define _entry_root_ca(__arg_data, __indent) \
+ { \
+ .long_name = "root-ca", .short_name = 0, .flags = G_OPTION_FLAG_NONE, \
+ .arg = G_OPTION_ARG_FILENAME, .arg_data = __arg_data, \
+ .description = "Use FILE as the trusted root CA instead the\n" __indent \
+ "root CAs that are installed on the system (optional).\n", \
+ .arg_description = "FILE", \
}
/* NOTE REQUIRED */

View File

@ -0,0 +1,92 @@
From 0748d365a60477c96cb9f6a12e9dbe547d549e1f Mon Sep 17 00:00:00 2001
From: Marc Hartmayer <mhartmay@linux.ibm.com>
Date: Tue, 12 Mar 2024 09:33:19 +0000
Subject: [PATCH] genprotimg/**/Makefile: Fix staged installs
Fix the support for staged installs. The Makefile variable `PKGDATADIR`
uses `DESTDIR` for all Makefile target, but actually it should only be
used for the `install*` and `uninstall*` targets. [1] Fix this by using
`DESTDIR` only for `install*` targets - uninstall* targets are not
supported by s390-tools.
Before this change, if `DESTDIR` was set for staged installs,
`genprotimg` has tried to find the bootloader binaries at the temporary
installation path `$DESTDIR$(TOOLS_DATADIR)/genprotimg/` instead of
`$(TOOLS_DATADIR)/genprotimg`.
[1] https://www.gnu.org/prep/standards/html_node/DESTDIR.html
Fixes: 65b9fc442c1a ("genprotimg: introduce new tool for the creation of PV images")
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
genprotimg/Makefile | 6 +++---
genprotimg/boot/Makefile | 8 ++++----
genprotimg/src/Makefile | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/genprotimg/Makefile b/genprotimg/Makefile
index 8c9f7048..6a2e37e4 100644
--- a/genprotimg/Makefile
+++ b/genprotimg/Makefile
@@ -3,7 +3,7 @@ include ../common.mak
.DEFAULT_GOAL := all
-PKGDATADIR := "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg"
+PKGDATADIR := "$(TOOLS_DATADIR)/genprotimg"
TESTS :=
SUBDIRS := boot src man
RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive
@@ -11,8 +11,8 @@ RECURSIVE_TARGETS := all-recursive install-recursive clean-recursive
all: all-recursive
install: install-recursive
- $(INSTALL) -d -m 755 "$(PKGDATADIR)"
- $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 samples/check_hostkeydoc "$(PKGDATADIR)"
+ $(INSTALL) -d -m 755 "$(DESTDIR)$(PKGDATADIR)"
+ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 samples/check_hostkeydoc "$(DESTDIR)$(PKGDATADIR)"
clean: clean-recursive
diff --git a/genprotimg/boot/Makefile b/genprotimg/boot/Makefile
index 799df9cc..73f3c9a8 100644
--- a/genprotimg/boot/Makefile
+++ b/genprotimg/boot/Makefile
@@ -7,7 +7,7 @@ DEBUG_FILES := $(addsuffix .debug,$(FILES))
ifeq ($(HOST_ARCH),s390x)
ZIPL_DIR := $(rootdir)/zipl
ZIPL_BOOT_DIR := $(ZIPL_DIR)/boot
-PKGDATADIR := $(DESTDIR)$(TOOLS_DATADIR)/genprotimg
+PKGDATADIR := $(TOOLS_DATADIR)/genprotimg
INCLUDE_PATHS := $(ZIPL_BOOT_DIR) $(ZIPL_DIR)/include $(rootdir)/include
INCLUDE_PARMS := $(addprefix -I,$(INCLUDE_PATHS))
@@ -86,9 +86,9 @@ stage3b.elf: head.o $(ZIPL_OBJS)
@chmod a-x $@
install: stage3a.bin stage3b_reloc.bin
- $(INSTALL) -d -m 755 "$(PKGDATADIR)"
- $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin "$(PKGDATADIR)"
- $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin "$(PKGDATADIR)"
+ $(INSTALL) -d -m 755 "$(DESTDIR)$(PKGDATADIR)"
+ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3a.bin "$(DESTDIR)$(PKGDATADIR)"
+ $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 stage3b_reloc.bin "$(DESTDIR)$(PKGDATADIR)"
else
# Don't generate the dependency files (see `common.mak` for the
diff --git a/genprotimg/src/Makefile b/genprotimg/src/Makefile
index 08734bff..d447e6cf 100644
--- a/genprotimg/src/Makefile
+++ b/genprotimg/src/Makefile
@@ -3,7 +3,7 @@ include ../../common.mak
bin_PROGRAM = genprotimg
-PKGDATADIR ?= "$(DESTDIR)$(TOOLS_DATADIR)/genprotimg"
+PKGDATADIR ?= "$(TOOLS_DATADIR)/genprotimg"
SRC_DIR := $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
TOP_SRCDIR := $(SRC_DIR)/../
ROOT_DIR = $(TOP_SRC_DIR)/../../

View File

@ -0,0 +1,28 @@
From: Jiri Bohac <jbohac@suse.cz>
References: bsc#1219471
Subject: include 59-zfcp-compat.rules in kdump initrd
kdump uses a random one of the by-path symlinks to refer to the target
partition.
With 59-zfcp-compat.rules added to the SUSE package, symlinks in the form
/dev/disk/by-path/ccw-*.*.*-zfcp-*:*-part* are created. If kdump uses this symlink when generating
the kdump initrd it will fail on boot beacause the udev rule is missing in the kdump initrd
and the symlink not created in the kdump environment.
Fix this by including 59-zfcp-compat.rules in the kdump initrd.
---
zdev/dracut/95zdev-kdump/module-setup.sh | 1 +
1 file changed, 1 insertion(+)
--- a/zdev/dracut/95zdev-kdump/module-setup.sh
+++ b/zdev/dracut/95zdev-kdump/module-setup.sh
@@ -78,6 +78,7 @@
inst_multiple /lib/s390-tools/zdev-from-dasd_mod.dasd
inst_rules "59-dasd.rules"
+ inst_rules "59-zfcp-compat.rules"
# Obtain kdump target device configuration

View File

@ -0,0 +1,112 @@
From 001c5aa5d40ffa7a40d64416c43c67004de29b8f Mon Sep 17 00:00:00 2001
From: Thomas Blume <Thomas.Blume@suse.com>
Date: Thu, 28 Mar 2024 13:32:46 +0100
Subject: [PATCH] parse ipl device for activation
ported from dracut modules
---
zdev/dracut/95zdev/parse-dasd.sh | 20 +++++++++++--
zdev/dracut/95zdev/parse-zfcp.sh | 56 +++++++++++++++++++++++++--------------
2 files changed, 54 insertions(+), 22 deletions(-)
--- a/zdev/dracut/95zdev/parse-dasd.sh
+++ b/zdev/dracut/95zdev/parse-dasd.sh
@@ -10,6 +10,8 @@
# parameters are evaluated and used to configure dasd devices.
#
+zdev_dasd_base_args="--no-settle --yes --no-root-update --force"
+
# shellcheck source=/dev/null
type zdev_parse_dasd_list > /dev/null 2>&1 || . /lib/s390-tools/zdev-from-dasd_mod.dasd
@@ -27,9 +29,21 @@
zdev_parse_rd_dasd() {
local _zdev_dasd _zdev_dasd_list
- for _zdev_dasd in $(getargs rd.dasd -d 'rd_DASD='); do
- _zdev_dasd_list="${_zdev_dasd_list:+${_zdev_dasd_list},}$_zdev_dasd"
- done
+ # autodetect active bootdev from zipl device
+ if ! getargbool 0 'rd.dasd' \
+ && [[ -f /sys/firmware/ipl/ipl_type ]] \
+ && [[ $(< /sys/firmware/ipl/ipl_type) == "ccw" ]]; then
+ read -r _ccw < /sys/firmware/ipl/device
+
+ if lszdev --offline "$_ccw" &>/dev/null; then
+ chzdev --offline --existing --enable --active $zdev_dasd_base_args \
+ dasd "$_ccw"
+ fi
+ else
+ for _zdev_dasd in $(getargs rd.dasd -d 'rd_DASD='); do
+ _zdev_dasd_list="${_zdev_dasd_list:+${_zdev_dasd_list},}$_zdev_dasd"
+ done
+ fi
echo "$_zdev_dasd_list"
}
--- a/zdev/dracut/95zdev/parse-zfcp.sh
+++ b/zdev/dracut/95zdev/parse-zfcp.sh
@@ -12,25 +12,43 @@
zdev_zfcp_base_args="--no-settle --yes --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"
- echo "rd.zfcp ${zdev_zfcp_arg} :" | zdev_vinfo
- if [ "$#" -eq 1 ]; then
- # shellcheck disable=SC2086
- chzdev --enable --persistent $zdev_zfcp_base_args \
- zfcp-host "$args" 2>&1 | zdev_vinfo
- else
+zdev_vinfo() {
+ local _zdev_vinfo_line
+ while read -r _zdev_vinfo_line || [ -n "$_zdev_vinfo_line" ]; do
+ # Prefix "<30>" represents facility LOG_DAEMON 3 and loglevel INFO 6:
+ # (facility << 3) | level.
+ echo "<30>dracut: $_zdev_vinfo_line" > /dev/kmsg
+ done
+}
+
+# autodetect active bootdev from zipl device
+if ! getargbool 0 'rd.zfcp' \
+ && [[ -f /sys/firmware/ipl/ipl_type ]] \
+ && [[ $(< /sys/firmware/ipl/ipl_type) == "fcp" ]]; then
+ chzdev --offline --existing --enable --active $zdev_zfcp_base_args \
+ zfcp-host 2>&1 | zdev_vinfo
+else
+ 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
- chzdev --enable --persistent $zdev_zfcp_base_args \
- zfcp-lun "$args" 2>&1 | zdev_vinfo
- fi
- )
-done
+ set -- $zdev_zfcp_arg
+ IFS=":" args="$*"
+ IFS="$IFS_SAVED"
+ echo "rd.zfcp ${zdev_zfcp_arg} :" | zdev_vinfo
+ if [ "$#" -eq 1 ]; then
+ # shellcheck disable=SC2086
+ chzdev --enable --persistent $zdev_zfcp_base_args \
+ zfcp-host "$args" 2>&1 | zdev_vinfo
+ else
+ # shellcheck disable=SC2086
+ chzdev --enable --persistent $zdev_zfcp_base_args \
+ zfcp-lun "$args" 2>&1 | zdev_vinfo
+ fi
+ )
+ done
+fi
+
unset zdev_zfcp_arg
unset zdev_zfcp_base_args

View File

@ -0,0 +1,19 @@
We strongly recommend that you get your z/OS support teams involved before installing this package.
The zdsfs command is a new feature provided by IBM with the s390-tools package in SLES12. The zdsfs command allows Linux systems to mount z/OS DASD volumes as a Linux file system. The zdsfs file system translates the z/OS data sets into Linux semantics.
Through the zdsfs file system, applications on Linux can read z/OS physical sequential data sets (PS) and partitioned data sets (PDS) on the DASD. If implemented improperly, or without the knowledge and cooperation of the systems programmers and information security professionals responsible for the z/OS system, the zdsfs command represents a potentially very serious security and data integrity exposure.
There are a number of factors to consider if you choose to install this package. A necessarily incomplete list of these would be:
- Through the zdsfs file system, whole DASD volumes are accessible to Linux
- This access is not controlled or detectable by any z/OS security or auditing mechanisms.
- This access is not controlled by any z/OS "locking" facility such as provided by ENQ, GRS, etc.
- To avoid data inconsistencies, ensure the DASD volumes are offline to z/OS before you mount them in Linux.
- To minimize security problems, you should dedicate the z/OS DASD volumes for the sole purpose of providing data to Linux.
- To share z/OS data with Linux, copy it to a dataset on that separate volume.
- Because the datasets will be accessed outside of z/OS, they will appear to have never been read after creation.
- You should ensure the datasets that Linux is to access are on a separate volume that is not used for automatic dataset allocation and that is not under System Managed Storage (SMS) control. This prevents dataset migration since they will appear to never be used (except when you update them), and it avoids unaudited access to datasets that are not intended for access by the Linux server.
- When running Linux native in an LPAR, ensure that the LPAR has access only to the specific z/OS volumes that contain the data to be accessed by Linux.
- By default, only the Linux user who mounts the zdsfs file system has access to it.
By confirming this caution, you are acknowledging that you are aware there are potential data security and integrity exposures involved in the use of this package, and that you want to install it anyway.

4682
s390-tools.changes Normal file

File diff suppressed because it is too large Load Diff

838
s390-tools.spec Normal file
View File

@ -0,0 +1,838 @@
#
# spec file for package s390-tools
#
# Copyright (c) 2024 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
# needssslcertforbuild
#Compat macro for new _fillupdir macro introduced in Nov 2017
%if ! %{defined _fillupdir}
%define _fillupdir %{_localstatedir}/adm/fillup-templates
%endif
%if 0%{?suse_version} < 1550 && 0%{?sle_version} <= 150300
# systemd-rpm-macros is wrong in 15.3 and below
%define _modprobedir /lib/modprobe.d
%endif
%global modprobe_d_files 90-s390-tools.conf
%if 0%{?suse_version} >= 1550
%define _mysbindir %{_sbindir}
%else
%define _mysbindir /sbin
%endif
Name: s390-tools
Version: 2.35.0
Release: 0
Summary: S/390 tools like zipl and dasdfmt for s390x (plus selected tools for x86_64)
License: MIT
Group: System/Kernel
URL: https://github.com/ibm-s390-tools/s390-tools
Source: https://github.com/ibm-s390-tools/s390-tools/archive/v%{version}.tar.gz#/s390-tools-%{version}.tar.gz
Source1: s390-tools-rpmlintrc
Source2: zipl.conf
Source3: hsnc
Source4: sysconfig.hsnc
Source5: xpram
Source6: sysconfig.xpram
Source7: appldata
Source8: sysconfig.appldata
Source10: dasdro
%if 0%{?suse_version} >= 1550
Source11: dasd_reload.opensuse
Source12: mkdump.pl.opensuse
%else
Source11: dasd_reload.suse
Source12: mkdump.pl.suse
%endif
Source13: sysconfig.osasnmpd
Source14: zfcp_san_disc
Source15: mkdump.8
Source18: zpxe.rexx
Source19: rules.xpram
Source20: rules.hw_random
%if 0%{?suse_version} >= 1550
Source21: 59-graf.rules.opensuse
%else
Source21: 59-graf.rules.suse
%endif
Source22: s390-tools-zdsfs.caution.txt
%if 0%{?suse_version} >= 1550
Source23: README.SUSE.opensuse
%else
Source23: README.SUSE.suse
%endif
Source24: cputype
Source25: cputype.1
Source26: cio_ignore.service
Source27: setup_cio_ignore.sh
Source28: 59-prng.rules
Source29: 59-zfcp-compat.rules
Source30: 90-s390-tools.conf
%if 0%{?suse_version} >= 1550
Source31: detach_disks.sh.opensuse
Source32: killcdl.opensuse
%else
Source31: detach_disks.sh.suse
Source32: killcdl.suse
%endif
Source33: lgr_check
Source34: sysconfig.virtsetup
Source35: virtsetup.service
%if 0%{?suse_version} >= 1550
Source36: virtsetup.sh.opensuse
%else
Source36: virtsetup.sh.suse
%endif
Source37: appldata.service
Source38: hsnc.service
%if 0%{?suse_version} >= 1550
Source39: vmlogrdr.service.opensuse
%else
Source39: vmlogrdr.service.suse
%endif
Source40: xpram.service
Source41: pkey.conf
### Obsolete scripts and man pages to be removed once changes in other tools are made
### That's been delayed to at least SLES12 SP1, but I'm leaving the comments here.
Source86: read_values.c
Source87: read_values.8
Source88: ctc_configure
%if 0%{?suse_version} >= 1550
Source89: dasd_configure.opensuse
Source90: iucv_configure.opensuse
%else
Source89: dasd_configure.suse
Source90: iucv_configure.suse
%endif
Source91: qeth_configure
Source92: zfcp_disk_configure
Source93: zfcp_host_configure
Source94: ctc_configure.8
Source95: dasd_configure.8
Source96: iucv_configure.8
Source97: qeth_configure.8
Source98: zfcp_disk_configure.8
Source99: zfcp_host_configure.8
###
Source200: cargo_config
Source201: vendor.tar.gz
###
###
# IBM patches
###
# SUSE patches
Patch900: s390-tools-sles12-zipl_boot_msg.patch
Patch901: s390-tools-sles15-sysconfig-compatible-dumpconf.patch
Patch902: s390-tools-sles12-create-filesystem-links.patch
%if 0%{?suse_version} >= 1550
Patch903: s390-tools-sles12-update-by_id-links-on-change-and-add-action.patch.opensuse
%else
Patch903: s390-tools-sles12-update-by_id-links-on-change-and-add-action.patch.suse
%endif
Patch904: s390-tools-sles15sp3-Allow-multiple-device-arguments.patch
Patch905: s390-tools-sles15sp3-Format-devices-in-parallel.patch
Patch906: s390-tools-sles15sp3-Implement-Y-yast_mode.patch
Patch907: s390-tools-sles15sp3-Implement-f-for-backwards-compability.patch
Patch908: s390-tools-sles15sp3-dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
Patch909: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
Patch910: s390-tools-sles15sp1-11-zdev-Do-not-call-zipl-on-initrd-update.patch
Patch911: s390-tools-sles15sp5-remove-no-pie-link-arguments.patch
Patch912: s390-tools-ALP-zdev-live.patch
Patch913: s390-tools-sles15sp6-kdump-initrd-59-zfcp-compat-rules.patch
Patch914: s390-tools-slfo-01-parse-ipl-device-for-activation.patch
###
BuildRequires: curl-devel
BuildRequires: dracut
BuildRequires: fuse3-devel
BuildRequires: gcc13
BuildRequires: gcc13-c++
BuildRequires: gettext-tools
BuildRequires: glib2-devel
BuildRequires: glibc-devel-static
BuildRequires: libcryptsetup-devel > 2.0.3
BuildRequires: libjson-c-devel
BuildRequires: libxml2-devel
BuildRequires: mdevctl
BuildRequires: ncurses-devel
BuildRequires: net-snmp-devel
BuildRequires: openssl-devel >= 1.1.1l
BuildRequires: pesign-obs-integration
BuildRequires: systemd-devel
BuildRequires: tcpd-devel
BuildRequires: zlib-devel-static
### s390x
%ifarch s390x
BuildRequires: kernel-zfcpdump
BuildRequires: perl-Bootloader >= 0.4.15
BuildRequires: qclib-devel-static
%endif
### Cargo
BuildRequires: rust
BuildRequires: cargo
BuildRequires: cargo-packaging
BuildRequires: openssl
###
# Don't build with pie to avoid problems with zipl
#!BuildIgnore: gcc-PIE
Requires: coreutils
Requires: procps
Requires: util-linux
%ifarch s390x
Requires: gawk
Requires: perl-base
Requires: rsync
Requires: s390-tools-genprotimg-data
Requires: tar
%endif
Requires(post): %fillup_prereq
Requires(post): permissions
Requires(pre): shadow
Recommends: blktrace
Provides: s390utils:/sbin/dasdfmt
Provides: group(cpacfstats)
Provides: group(ts-shell)
Provides: group(zkeyadm)
%ifarch x86_64
Recommends: s390-tools-genprotimg-data
%endif
###
ExclusiveArch: s390x x86_64
%description
This package contains the tools (s390x, x86_64) needed to use Linux on IBM z Systems
and exploit many of the various capabilities of the hardware or z/VM. For example:
- s390x
dasdfmt - low-level format tool for ECKD DASD
fdasd - partitions ECKD DASDs with z/OS compatible disk layout
zipl - boot loader and dump DASD initializer
zgetdump - tool to get linux system dumps from DASD
- x86_64
genprotimg - create a protected virtualization image
pvattest - create, perform, and verify protected virtualization attestation measurements
pvsecret - manage secrets for IBM Secure Execution guests.
pvapconfig - used to automatically set up the AP configuration within an IBM Secure Execution guest.
Warning: There is an auxiliary data package - s390-tools-genprotimg-data.
To install s390-tools properly, please use:
'sudo zypper install s390-tools s390-tools-genprotimg-data'
%package -n osasnmpd
Summary: OSA-Express SNMP subagent
License: GPL-2.0-or-later
Group: Productivity/Networking/Other
Requires: perl
%description -n osasnmpd
Supports management information bases (MIBs) provided by OSA-Express
Fast Ethernet, Gigabit Ethernet, High Speed Token Ring and ATM Ethernet
LAN Emulation features in QDIO mode.
It extends the capabilities of the net-snmp master agent (snmpd) and
communicates with him via the AgentX protocol.
%package zdsfs
Summary: QSAM access to z/OS data
License: GPL-2.0-or-later AND NonFree
Group: Productivity/Networking/Other
%description zdsfs
Use the zdsfs command for read access to z/OS data sets stored on one or more DASDs.
The zdsfs file system translates the record-based z/OS data sets to UNIX file system
semantics. After mounting the devices, you can use common Linux tools to access
the files on the disk. Physical sequential data sets are represented as files.
Partitioned data sets are represented as directories, with each member being
represented as a file in that directory.
%package hmcdrvfs
Summary: HMC drive file system based on FUSE
License: GPL-2.0-only
Group: System/Filesystems
Requires: fuse
%description hmcdrvfs
This package contains a HMC drive file system based on FUSE and a tool
to list files and directories.
%package -n libekmfweb1
Summary: IBM Enterprise Key Management Foundation - Web Edition client library
License: MIT
Group: System/Libraries
%description -n libekmfweb1
libekmfweb1 is a client library that provides access to IBM' Enterprise Key
Management Foundation Web Edition.0 EKMF Web provides efficient and
security-rich centralized key management for IBM z/OS data set encryption
on IBM Z servers.
%package -n libekmfweb1-devel
Summary: IBM Enterprise Key Management Foundation - Web Edition client library
License: MIT
Group: Development/Libraries/C and C++
Requires: libekmfweb1 = %{version}
%description -n libekmfweb1-devel
libekmfweb1 is a client library that provides access to IBM' Enterprise Key
Management Foundation Web Edition.0 EKMF Web provides efficient and
security-rich centralized key management for IBM z/OS data set encryption
on IBM Z servers.
%package -n libkmipclient1
Summary: IBM Key Management Interoperability Protocol (KMIP) client library
License: MIT
Group: System/Libraries
%description -n libkmipclient1
Key Management Interoperability Protocol (KMIP) is a client/server
communication protocol for the storage and maintenance of key,
certificate, and secret objects. This client library enables secure
creation and storage of cryptographic objects on the IBM Security Key
Lifecycle Manager server. You must configure client devices to connect
to the server for key management operations.
%package -n libkmipclient1-devel
Summary: Header files for the IBM Z KMIP client library
License: MIT
Group: Development/Libraries/C and C++
Requires: libkmipclient1 = %{version}
%description -n libkmipclient1-devel
This package provides the header files and symbolic link to the
shared library for the IBM Z KMIP client library.
%package chreipl-fcp-mpath
Summary: Use multipath information for re-IPL path failover
License: MIT
Group: System/Boot
BuildRequires: bash
BuildRequires: coreutils
## Required for build+install with ENABLE_DOC=1
#BuildRequires: pandoc
BuildRequires: sed
#BuildRequires: gawk
#BuildRequires: gzip
Requires: bash
# Required for use with HAVE_DRACUT=1
Requires: dracut
Requires: multipath-tools
Requires: udev
Requires(post): udev
%description chreipl-fcp-mpath
The chreipl-fcp-mpath toolset monitors udev events about paths to the
re-IPL volume. If the currently configured FCP re-IPL path becomes
unavailable, the toolset checks for operational paths to the same
volume. If available, it reconfigures the FCP re-IPL settings to use an
operational path.
%package genprotimg-data
Summary: Auxiliary data used by genprotimg
License: MIT
Group: System/Boot
BuildArch: noarch
Requires(pre): filesystem
%description genprotimg-data
The genprotimg allows preparing and analyzing boot images
in the realm of IBM Secure Execution on a trusted environment,
such as the laptop of an admin by limiting the build targets
depending on the defined or detected host architecture.
This package provides auxiliary data used by genprotimg.
### *** s390x ************************************************************************* ###
%ifarch s390x
%prep
%autosetup -p1
cp -vi %{SOURCE22} CAUTION
install -D -m 0644 %{SOURCE200} .cargo/config
tar -xzf %{SOURCE201}
%build
# The "DISTRELEASE=%%{release}" needs to be on both the make and make install
# commands, since make install runs sed commands against various scripts to
# modify the "-v" output appropriately.
export OPT_FLAGS="%{optflags}"
export KERNELIMAGE_MAKEFLAGS="%%{?_smp_mflags}"
%make_build \
ZFCPDUMP_DIR=%{_prefix}/lib/s390-tools/zfcpdump \
DISTRELEASE=%{release} \
UDEVRUNDIR=/run/udev \
HAVE_CARGO=1 \
HAVE_DRACUT=1 \
CC=gcc-13 \
CXX=g++-13
### all
gcc-13 -static -o read_values ${OPT_FLAGS} %{SOURCE86} -lqc
%install
mkdir -p %{buildroot}/boot/zipl
mkdir -p %{buildroot}%{_sysconfdir}/zkey/repository
%make_install \
ZFCPDUMP_DIR=%{_prefix}/lib/s390-tools/zfcpdump \
DISTRELEASE=%{release} \
SYSTEMDSYSTEMUNITDIR=%{_unitdir} \
UDEVRUNDIR=/run/udev \
HAVE_CARGO=1 \
HAVE_DRACUT=1 \
CC=gcc-13 \
CXX=g++-13
### all
# The make install command puts things in /etc/sysconfig and not the
# fillup-templates directory. Let's try moving them where they belong
mkdir -p %{buildroot}%{_fillupdir}
pushd %{buildroot}%{_sysconfdir}/sysconfig/
for sysconffile in *
do mv -vi $sysconffile %{buildroot}%{_fillupdir}/sysconfig.$sysconffile
done
popd
install -m 755 read_values %{buildroot}/%{_bindir}/
install -m644 -t %{buildroot}/%{_mandir}/man8 %{SOURCE87}
# The "usrmerge" has happened in openSUSE:Factory, but not yet in SLES.
# Make sure we look for the zfcpdump kernel image in the right place.
%if 0%{?suse_version} >= 1550
install -D -m600 %{_prefix}/lib/modules/*-zfcpdump/image %{buildroot}%{_prefix}/lib/s390-tools/zfcpdump/zfcpdump-image
%else
install -D -m600 /boot/image-*-zfcpdump %{buildroot}%{_prefix}/lib/s390-tools/zfcpdump/zfcpdump-image
%endif
install -D -m644 etc/cpuplugd.conf %{buildroot}%{_sysconfdir}/cpuplugd.conf
install -D -m644 etc/udev/rules.d/40-z90crypt.rules %{buildroot}%{_prefix}/lib/udev/rules.d/40-z90crypt.rules
install -D -m644 etc/udev/rules.d/57-osasnmpd.rules %{buildroot}%{_prefix}/lib/udev/rules.d/57-osasnmpd.rules
install -D -m644 etc/udev/rules.d/59-dasd.rules %{buildroot}%{_prefix}/lib/udev/rules.d/59-dasd.rules
install -D -m644 etc/udev/rules.d/90-cpi.rules %{buildroot}%{_prefix}/lib/udev/rules.d/90-cpi.rules
mv iucvterm/doc/ts-shell/iucvconn_on_login %{buildroot}%{_bindir}/iucvconn_on_login
install -D -m644 %{SOURCE26} %{buildroot}/%{_unitdir}/cio_ignore.service
install -D -m755 %{SOURCE27} %{buildroot}%{_prefix}/lib/systemd/scripts/setup_cio_ignore.sh
install -D -m755 %{SOURCE31} %{buildroot}%{_prefix}/lib/systemd/scripts/detach_disks.sh
install -D -m644 %{SOURCE35} %{buildroot}/%{_unitdir}/virtsetup.service
install -D -m755 %{SOURCE36} %{buildroot}%{_prefix}/lib/systemd/scripts/virtsetup.sh
install -D -m644 %{SOURCE37} %{buildroot}/%{_unitdir}/appldata.service
install -D -m644 %{SOURCE38} %{buildroot}/%{_unitdir}/hsnc.service
install -D -m644 %{SOURCE39} %{buildroot}/%{_unitdir}/vmlogrdr.service
install -D -m644 %{SOURCE40} %{buildroot}/%{_unitdir}/xpram.service
install -D -m644 %{SOURCE41} %{buildroot}%{_prefix}/lib/modules-load.d/pkey.conf
cp %{SOURCE18} zpxe.rexx
cp %{SOURCE2} zipl.conf.sample
cp %{SOURCE23} README.SUSE
cd %{buildroot}
install -D -m755 %{SOURCE3} %{buildroot}%{_prefix}/lib/systemd/scripts/hsnc
install -D -m644 %{SOURCE4} %{buildroot}%{_fillupdir}/sysconfig.hsnc
install -D -m755 %{SOURCE5} %{buildroot}%{_prefix}/lib/systemd/scripts/xpram
install -D -m644 %{SOURCE6} %{buildroot}%{_fillupdir}/sysconfig.xpram
install -D -m755 %{SOURCE7} %{buildroot}%{_prefix}/lib/systemd/scripts/appldata
install -D -m644 %{SOURCE8} %{buildroot}%{_fillupdir}/sysconfig.appldata
install -D -m755 %{SOURCE10} %{buildroot}%{_mysbindir}/dasdro
install -D -m755 %{SOURCE11} %{buildroot}%{_mysbindir}/dasd_reload
install -D -m755 %{SOURCE12} %{buildroot}%{_mysbindir}/mkdump
install -D -m644 %{SOURCE13} %{buildroot}%{_fillupdir}/sysconfig.osasnmpd
install -D -m755 %{SOURCE14} %{buildroot}%{_mysbindir}/zfcp_san_disc
install -D -m644 %{SOURCE15} %{buildroot}/%{_mandir}/man8
install -D -m644 %{SOURCE19} %{buildroot}%{_prefix}/lib/udev/rules.d/52-xpram.rules
install -D -m644 %{SOURCE20} %{buildroot}%{_prefix}/lib/udev/rules.d/52-hw_random.rules
install -D -m644 %{SOURCE21} %{buildroot}%{_prefix}/lib/udev/rules.d/59-graf.rules
install -D -m644 %{SOURCE28} %{buildroot}%{_prefix}/lib/udev/rules.d/59-prng.rules
install -D -m644 %{SOURCE29} %{buildroot}%{_prefix}/lib/udev/rules.d/59-zfcp-compat.rules
install -D -m644 %{SOURCE30} %{buildroot}%{_modprobedir}/90-s390-tools.conf
install -D -m755 %{SOURCE32} %{buildroot}%{_mysbindir}/killcdl
install -D -m755 %{SOURCE33} %{buildroot}%{_mysbindir}/lgr_check
install -D -m644 %{SOURCE34} %{buildroot}%{_fillupdir}/sysconfig.virtsetup
if [ ! -d %{_mysbindir} ]; then
rm -f %{_mysbindir}
mkdir -p %{_mysbindir}
fi
(cd %{buildroot}%{_sbindir}; ln -s service rcappldata)
(cd %{buildroot}%{_sbindir}; ln -s service rchsnc)
(cd %{buildroot}%{_sbindir}; ln -s service rcvmlogrdr)
(cd %{buildroot}%{_sbindir}; ln -s service rcxpram)
(cd %{buildroot}%{_sbindir}; ln -s service rccio_ignore)
(cd %{buildroot}%{_sbindir}; ln -s service rccpacfstatsd)
(cd %{buildroot}%{_sbindir}; ln -s service rccpi)
(cd %{buildroot}%{_sbindir}; ln -s service rccpuplugd)
(cd %{buildroot}%{_sbindir}; ln -s service rcdumpconf)
(cd %{buildroot}%{_sbindir}; ln -s service rcmon_fsstatd)
(cd %{buildroot}%{_sbindir}; ln -s service rcmon_procd)
(cd %{buildroot}%{_sbindir}; ln -s service rcvirtsetup)
if [ ! -d %{_bindir} ]; then
rm -f %{_bindir}
mkdir -p %{_bindir}
fi
install -D -m755 %{SOURCE24} %{buildroot}%{_bindir}/cputype
install -m644 -t %{buildroot}/%{_mandir}/man8 %{SOURCE25}
# If building for openSUSE, move all the binaries installed via
# the IBM-provided Makefile from /sbin to /usr/sbin/ to
# align with the openSUSE "usrmerge" project
%if 0%{?suse_version} >= 1550
mv -vi %{buildroot}/sbin/* %{buildroot}%{_mysbindir}/
%endif
### Obsolete scripts and man pages to be removed once changes in other tools are made
install -m755 -t %{buildroot}%{_mysbindir}/ %{SOURCE88} %{SOURCE91} %{SOURCE92} %{SOURCE93}
install %{SOURCE89} %{buildroot}%{_mysbindir}/dasd_configure
install %{SOURCE90} %{buildroot}%{_mysbindir}/iucv_configure
install -m644 -t %{buildroot}/%{_mandir}/man8 %{SOURCE94} %{SOURCE95} %{SOURCE96} %{SOURCE97} %{SOURCE98} %{SOURCE99}
###
### lsmem/chmem have been added to util-linux
rm -fv %{buildroot}%{_mandir}/man8/lsmem.8*
rm -fv %{buildroot}%{_mandir}/man8/chmem.8*
rm -fv %{buildroot}%{_mysbindir}/lsmem
rm -fv %{buildroot}%{_mysbindir}/chmem
###
find . ! -type d |
sed 's/^.//;\-/man/-s/^.*$/%doc &.gz/' > %{_builddir}/%{name}-filelist
grep -v -E 'osasnmp|etc/ziplenv|\.conf$|ekmfweb.so|ekmfweb.h|kmipclient|kmip/profiles/.*profile$|chreipl-fcp-mpath' %{_builddir}/%{name}-filelist >%{_builddir}/%{name}.list
grep osasnmp[^-] %{_builddir}/%{name}-filelist >%{_builddir}/%{name}.osasnmp
touch boot/zipl/active_devices.txt
mkdir -p ./%{_libexecdir}/net-snmp/agents
cd ./%{_libexecdir}/net-snmp/agents
cat <<EOT >osasnmpd
#!/bin/sh
PIDFILE=%{_localstatedir}/run/osasnmpd.pid
function cleanup
{
rm -f \$PIDFILE
kill \`cat %{_localstatedir}/run/osasnmpd.real.pid\`
}
. %{_sysconfdir}/sysconfig/osasnmpd
trap cleanup 0
echo \$\$ >\$PIDFILE
%{_mysbindir}/osasnmpd -f -P %{_localstatedir}/run/osasnmpd.real.pid \$OSASNMPD_PARAMETERS "\$@"
EOT
chmod 755 osasnmpd
export BRP_PESIGN_FILES='/lib/s390-tools/stage3.bin'
%verifyscript
%verify_permissions -e %{_localstatedir}/log/ts-shell/
%pre
# check for ts-shell group or create it
getent group ts-shell >/dev/null 2>&1 || groupadd -r ts-shell
# check for zkeyadm group or create it
getent group zkeyadm >/dev/null 2>&1 || groupadd -r zkeyadm
# check for cpacfstats group or create it
getent group cpacfstats >/dev/null 2>&1 || groupadd -r cpacfstats
%service_add_pre appldata.service
%service_add_pre cio_ignore.service
%service_add_pre cpacfstatsd.service
%service_add_pre cpi.service
%service_add_pre cpuplugd.service
%service_add_pre dumpconf.service
%service_add_pre hsnc.service
%service_add_pre mon_fsstatd.service
%service_add_pre mon_procd.service
%service_add_pre virtsetup.service
%service_add_pre vmlogrdr.service
%service_add_pre xpram.service
# Avoid restoring outdated stuff in posttrans
for _f in %{?modprobe_d_files}; do
[ ! -f "/etc/modprobe.d/${_f}.rpmsave" ] || \
mv -f "/etc/modprobe.d/${_f}.rpmsave" "/etc/modprobe.d/${_f}.rpmsave.old" || :
done
%post
read INITPGM < /proc/1/comm
if [ "${INITPGM}" = "systemd" ]; then
echo "Running systemctl daemon-reload."
systemctl daemon-reload
fi
%set_permissions %{_localstatedir}/log/ts-shell/
# Create symbolic links to the scripts from setup and boot directories
%service_add_post appldata.service
%service_add_post cio_ignore.service
%service_add_post cpacfstatsd.service
%service_add_post cpi.service
%service_add_post cpuplugd.service
%service_add_post dumpconf.service
%service_add_post hsnc.service
%service_add_post mon_fsstatd.service
%service_add_post mon_procd.service
%service_add_post virtsetup.service
%service_add_post vmlogrdr.service
%service_add_post xpram.service
# Create the initial versions of the sysconfig files:
%{fillup_only -n appldata}
%{fillup_only -n cpi}
%{fillup_only -n dumpconf}
%{fillup_only -n hsnc}
%{fillup_only -n mon_fsstatd}
%{fillup_only -n mon_procd}
%{fillup_only -n mon_statd}
%{fillup_only -n virtsetup}
%{fillup_only -n xpram}
%triggerin -- kernel-default
grep -q '^%{_bindir}/ts-shell$' %{_sysconfdir}/shells \
|| echo "%{_bindir}/ts-shell" >> %{_sysconfdir}/shells
%{?regenerate_initrd_post}
%post -n osasnmpd
%{fillup_only -n osasnmpd}
%post -n libekmfweb1
ldconfig
%post -n libkmipclient1
ldconfig
%post chreipl-fcp-mpath
%udev_rules_update
%preun
%service_del_preun appldata.service
%service_del_preun cio_ignore.service
%service_del_preun cpacfstatsd.service
%service_del_preun cpi.service
%service_del_preun cpuplugd.service
%service_del_preun dumpconf.service
%service_del_preun hsnc.service
%service_del_preun mon_fsstatd.service
%service_del_preun mon_procd.service
%service_del_preun virtsetup.service
%service_del_preun vmlogrdr.service
%service_del_preun xpram.service
%postun
%service_del_postun appldata.service
%service_del_postun cio_ignore.service
%service_del_postun cpacfstatsd.service
%service_del_postun cpi.service
%service_del_postun cpuplugd.service
%service_del_postun dumpconf.service
%service_del_postun hsnc.service
%service_del_postun mon_fsstatd.service
%service_del_postun mon_procd.service
%service_del_postun virtsetup.service
%service_del_postun vmlogrdr.service
%service_del_postun xpram.service
%postun -n libekmfweb1
ldconfig
%postun -n libkmipclient1
ldconfig
# Even though SLES15+ is systemd based, the build service doesn't
# run it, so we have to make sure we can safely issue the
# systemctl command.
read INITPGM < /proc/1/comm
if [ "${INITPGM}" = "systemd" ]; then
echo "Running systemctl daemon-reload."
systemctl daemon-reload
fi
if [ ! -x /boot/zipl ]; then
echo "Attention, after uninstalling this package,"
echo "you will NOT be able to IPL from DASD anymore!!!"
fi
if test x$1 = x0; then
# remove ts-shell from /etc/shells
grep -v '^%{_bindir}/ts-shell$' %{_sysconfdir}/shells > %{_sysconfdir}/shells.ts-new
mv %{_sysconfdir}/shells.ts-new %{_sysconfdir}/shells
chmod 0644 %{_sysconfdir}/shells
fi
%{?regenerate_initrd_post}
%posttrans
# Migration of modprobe.conf files to _modprobedir
for _f in %{?modprobe_d_files}; do
[ ! -f "/etc/modprobe.d/${_f}.rpmsave" ] || \
mv -fv "/etc/modprobe.d/${_f}.rpmsave" "/etc/modprobe.d/${_f}" || :
done
%{?regenerate_initrd_posttrans}
%preun -n osasnmpd
%{stop_on_removal osasnmpd}
%files -f %{_builddir}/%{name}.list
%doc README.md
%doc README.SUSE
%doc iucvterm/doc/ts-shell
%doc zpxe.rexx
%doc zipl.conf.sample
%dir %{_sysconfdir}/iucvterm
%config %attr(0640,root,ts-shell) %{_sysconfdir}/iucvterm/ts-audit-systems.conf
%config %attr(0640,root,ts-shell) %{_sysconfdir}/iucvterm/ts-authorization.conf
%config %attr(0640,root,ts-shell) %{_sysconfdir}/iucvterm/ts-shell.conf
%config %attr(0640,root,ts-shell) %{_sysconfdir}/iucvterm/unrestricted.conf
%dir %attr(0770,root,zkeyadm) %{_sysconfdir}/zkey
%dir %attr(0770,root,zkeyadm) %{_sysconfdir}/zkey/kmip
%dir %attr(0770,root,zkeyadm) %{_sysconfdir}/zkey/kmip/profiles
%dir %attr(0770,root,zkeyadm) %{_sysconfdir}/zkey/repository
%config %{_sysconfdir}/zkey/kmip/profiles/*
%config(noreplace) %{_sysconfdir}/ziplenv
%dir %{_modprobedir}
%{_modprobedir}/90-s390-tools.conf
%config %{_sysconfdir}/cpuplugd.conf
%config %{_sysconfdir}/zkey/kms-plugins.conf
%config(noreplace) /boot/zipl/active_devices.txt
%dir %attr(2770,root,ts-shell) %{_localstatedir}/log/ts-shell
%dir %{_sysconfdir}/cmsfs-fuse
%config %attr(0640,root,root) %{_sysconfdir}/cmsfs-fuse/filetypes.conf
%dir %{_prefix}/lib/mdevctl
%dir %{_prefix}/lib/mdevctl/scripts.d
%dir %{_prefix}/lib/mdevctl/scripts.d/callouts
%dir %{_prefix}/lib/s390-tools
%dir %{_prefix}/lib/s390-tools/zfcpdump
%dir %{_prefix}/lib/udev/rules.d
%dir %{_prefix}/lib/systemd/scripts
%dir %{_datadir}/s390-tools
%dir %{_datadir}/s390-tools/netboot
%dir %{_datadir}/s390-tools/genprotimg
%dir %{_prefix}/lib/dracut/modules.d/95zdev
%dir %{_prefix}/lib/dracut/modules.d/95zdev-kdump
%dir %{_prefix}/lib/dracut/modules.d/96zdev-live
%dir %{_prefix}/lib/dracut/modules.d/99ngdump
%dir /boot/zipl
%dir %{_libdir}/zkey
%{_libdir}/zkey/zkey-ekmfweb.so
%dir /lib/s390-tools/
/lib/s390-tools/zipl.conf
%{_prefix}/lib/modules-load.d/pkey.conf
%exclude %{_prefix}/lib/udev/rules.d/57-osasnmpd.rules
%exclude %{_bindir}/zdsfs
%exclude %{_bindir}/hmcdrvfs
%exclude %{_sbindir}/lshmc
%exclude %{_mandir}/man1/zdsfs.1.gz
%exclude %{_mandir}/man1/hmcdrvfs.1.gz
%exclude %{_mandir}/man8/lshmc.8.gz
###
%dir /etc/mdevctl.d/scripts.d/
%dir /etc/mdevctl.d/scripts.d/callouts/
###
%exclude /lib/s390-tools/stage3.bin
%exclude %{_datadir}/s390-tools/genprotimg/stage3a.bin
%exclude %{_datadir}/s390-tools/genprotimg/stage3b_reloc.bin
###
%files -n osasnmpd -f %{_builddir}/%{name}.osasnmp
%{_libexecdir}/net-snmp/agents/osasnmpd
%files zdsfs
%doc CAUTION
%{_bindir}/zdsfs
%{_mandir}/man1/zdsfs.1%{?ext_man}
%files hmcdrvfs
%{_bindir}/hmcdrvfs
%{_sbindir}/lshmc
%{_mandir}/man1/hmcdrvfs.1%{?ext_man}
%{_mandir}/man8/lshmc.8%{?ext_man}
%files -n libekmfweb1
%{_libdir}/libekmfweb.so.*
%files -n libekmfweb1-devel
%{_libdir}/libekmfweb.so
%dir %attr(755,root,root) %{_includedir}/ekmfweb
%attr(644,root,root) %{_includedir}/ekmfweb/ekmfweb.h
%files -n libkmipclient1
%{_libdir}/libkmipclient.so.*
%files -n libkmipclient1-devel
%{_libdir}/libkmipclient.so
%dir %attr(755,root,root) %{_includedir}/kmipclient
%attr(644,root,root) %{_includedir}/kmipclient/kmipclient.h
%files chreipl-fcp-mpath
%doc chreipl-fcp-mpath/README.md
## Requires build+install with ENABLE_DOC=1
#doc chreipl-fcp-mpath/README.html
%dir %{_prefix}/lib/chreipl-fcp-mpath/
%{_prefix}/lib/chreipl-fcp-mpath/*
%{_prefix}/lib/dracut/dracut.conf.d/70-chreipl-fcp-mpath.conf
%{_prefix}/lib/udev/chreipl-fcp-mpath-is-ipl-tgt
%{_prefix}/lib/udev/chreipl-fcp-mpath-is-ipl-vol
%{_prefix}/lib/udev/chreipl-fcp-mpath-is-reipl-zfcp
%{_prefix}/lib/udev/chreipl-fcp-mpath-record-volume-identifier
%{_prefix}/lib/udev/chreipl-fcp-mpath-try-change-ipl-path
%{_udevrulesdir}/70-chreipl-fcp-mpath.rules
%{_mandir}/man7/chreipl-fcp-mpath.7%{?ext_man}
### genprotimg
%files genprotimg-data
/lib/s390-tools/stage3.bin
%{_datadir}/s390-tools/genprotimg/stage3a.bin
%{_datadir}/s390-tools/genprotimg/stage3b_reloc.bin
### _endif
### *** !s390x ************************************************************************* ###
### _ifarch x86_64
%else
%prep
%autosetup -p1
install -D -m 0644 %{SOURCE200} .cargo/config
tar -xzf %{SOURCE201}
%build
export OPT_FLAGS="%{optflags}"
export KERNELIMAGE_MAKEFLAGS="%%{?_smp_mflags}"
%make_build \
DISTRELEASE=%{release} \
UDEVRUNDIR=/run/udev \
HAVE_CARGO=1 \
HAVE_DRACUT=1
%install
%make_install \
DISTRELEASE=%{release} \
SYSTEMDSYSTEMUNITDIR=%{_unitdir} \
UDEVRUNDIR=/run/udev \
HAVE_CARGO=1 \
HAVE_DRACUT=1
%files
%{_prefix}/bin/*
%dir %{_datadir}/s390-tools
%dir %{_datadir}/s390-tools/genprotimg
%{_datadir}/s390-tools/genprotimg/check_hostkeydoc
%{_mandir}/man1/*
%endif
%changelog

16
setup_cio_ignore.sh Normal file
View File

@ -0,0 +1,16 @@
#!/bin/bash
#
# setup_cio_ignore
#
# Remove the device ids found in /boot/zipl/active_devices.txt
# from cio_ignore
#
if [ -e /boot/zipl/active_devices.txt ] ; then
while read dev etc ; do
[ "$dev" = "#" -o "$dev" = "" ] && continue;
cio_ignore -r $dev
done < /boot/zipl/active_devices.txt
fi
exit 0

35
sysconfig.appldata Normal file
View File

@ -0,0 +1,35 @@
# /etc/sysconfig/appldata
## Path: Kernel/APPLDATA
## Description: Linux - z/VM Monitor Stream
## Type: integer
## Default: 10000
#
# Polling interval in milliseconds
#
APPLDATA_INTERVAL=10000
## Type: list(yes,no)
## Default: yes
#
# Load module for collecting data related
# to memory management.
#
APPLDATA_MEM="yes"
## Type: list(yes,no)
## Default: yes
#
# Load module for collecting OS information
# (CPU utilization, running processes).
APPLDATA_OS="yes"
## Type: list(yes,no)
## Default: no
#
# Load module for collecting accumulated
# network statistics (Packets received/transmitted,
# dropped, errors, ...)
#
APPLDATA_NET_SUM="no"

23
sysconfig.hsnc Normal file
View File

@ -0,0 +1,23 @@
## Path: Hardware/Network
## Description: HiperSockets Network Concentrator Configuration
## Type: list(unicast,full)
## Default: unicast
#
# unicast means, only unicast forwarded between the hsint's and osaint's.
# this is the default mode
# full means, unicast, multicast and broadcast are forwarded, if supported
# by the hardware
#
operating_mode="unicast"
## Type: string
## Default: ""
#
# describes all HiperSockets interfaces involved in the HSN
#
hsi_int=""
## Type: string
## Default: ""
#
# describes the OSA interface connecting to other LANs
#
osa_int=""

14
sysconfig.osasnmpd Normal file
View File

@ -0,0 +1,14 @@
## Path: Network/SNMP/OSA Express SNMP agent
## Description: OSA Express SNMP agent parameters
## Type: string
## Default: ""
## ServiceRestart: snmpd
#
# OSA Express SNMP agent command-line parameters
#
# Enter the parameters you want to be passed on to the OSA Express SNMP
# agent.
#
# Example: OSASNMPD_PARAMETERS="-l /var/log/my_private_logfile"
#
OSASNMPD_PARAMETERS=""

48
sysconfig.virtsetup Normal file
View File

@ -0,0 +1,48 @@
## Path: System/Virtualization/Virtsetup
## Description: System preparation for z/VM Live Guest Relocation
## Type: yesno
## Default: no
#
# Whether disks should be automatically detached from the guest or not
#
ZVM_DETACH_DISKS="no"
## Type: yesno
## Default: no
#
# If detaching disks from the guest, detach all disks not currently
# activated by Linux (as shown by lsdasd)?
ZVM_DETACH_ALL_UNUSED="no"
## Type: string
## Default: ""
#
# If detaching disks from the guest, which ones should be detached
#
ZVM_DISKS_TO_DETACH=""
## Type: string
## Default: ""
#
# If detaching disks from the guest, which ones should NOT be detached.
# If a disk is in this and ZVM_DISKS_TO_DETACH, the entry in this
# list takes precedence.
#
ZVM_DISKS_TO_NOT_DETACH=""
## Type: yesno
## Default: yes
#
# Should we check various conditions that might prevent relocation?
# Only conditions that can be determined by an unprivileged guest
# will be checked.
#
ZVM_WARN_ABOUT_POSSIBLE_LGR_PROBLEMS="yes"
## Type: yesno
## Default: yes
#
# Should we use the SCLP interface to inform PR/SM of the
# hostname of this system?
#
LPAR_SCLP_HOSTNAME="yes"

48
sysconfig.xpram Normal file
View File

@ -0,0 +1,48 @@
## Path: Kernel/XPRAM
## Description: configure XPRAM device
## Type: list(yes,no)
## Default: no
#
# Create an XPRAM device on this machine
#
XPRAM_START="no"
## Type: list(yes,no)
## Default: no
#
# Create the new device even if there is valid data on the device.
#
XPRAM_FORCE="no"
## Type: string
## Default: "xpram"
#
# Kernel module to load for the xpram device
#
XPRAM_MODULE="xpram"
## Type: string
## Default: "/dev/slram0"
#
# Device node for the xpram device
#
XPRAM_DEVNODE="/dev/slram0"
## Type: string
## Default: ""
#
# Mount point for the xpram device
#
XPRAM_MNTPATH="/abuild"
## Type: string
## Default: "ext2"
#
# Filesystem type for the xpram device
#
XPRAM_FSTYPE="ext2"
# Fix for SWAP priority setting
XPRAM_SWAP_PRI="42"

BIN
vendor.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

13
virtsetup.service Normal file
View File

@ -0,0 +1,13 @@
[Unit]
Description=Perform hypervisor-specific setup and cleanup tasks
DefaultDependencies=no
Wants=default.target
After=default.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/systemd/scripts/virtsetup.sh
[Install]
WantedBy=default.target

92
virtsetup.sh.opensuse Normal file
View File

@ -0,0 +1,92 @@
#!/bin/sh
#
# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Perform setup tasks based on what hypervisor is in charge.
#
# Source the sysconfig file
if [ -r /etc/sysconfig/virtsetup ]; then
. /etc/sysconfig/virtsetup
else echo "No /etc/sysconfig/virtsetup file was found."
exit 1
fi
#
# Get our hostname
#
my_hostname="$(hostname)"
#
# Find out the hypervisor we're running on/under.
#
hypervisor="$(/usr/bin/systemd-detect-virt)"
case "${hypervisor}" in
zvm)
if [ ! -c /dev/vmcp ]; then
modprobe vmcp
sleep 1
if [ ! -c /dev/vmcp ]; then
echo "Unable to load the vmcp kernel module."
exit 1
fi
fi
echo "The vmcp device driver is ready."
if [ "${ZVM_DETACH_DISKS}" == "yes" ]; then
echo "Detaching devices to prepare for Live Guest Relocation."
/usr/lib/systemd/scripts/detach_disks.sh
fi
if [ "${ZVM_WARN_ABOUT_POSSIBLE_LGR_PROBLEMS}" == yes ]; then
/usr/sbin/lgr_check
fi
;;
none)
hypervisor="lpar"
if [ "${LPAR_SCLP_HOSTNAME}" == "yes" ]; then
# If the sclp_cpi module is already loaded, we have to unload it
# so we can be sure it has the correct system name specified
# when we reload it again.
if grep -qw sclp_cpi /proc/modules 2>/dev/null; then
rmmod sclp_cpi
sleep 1
fi
if grep -qw sclp_cpi /proc/modules 2>/dev/null; then
echo "Unable to unload the sclp_cpi kernel module."
exit 1
fi
echo "Setting the LPAR name via the sclp_cpi module."
modprobe sclp_cpi system_name="$my_hostname"
if ! grep -qw sclp_cpi /proc/modules 2>/dev/null; then
echo "We were unable to load the sclp_cpi module to set the LPAR name."
exit 2
fi
fi
;;
kvm)
;;
*)
echo "An unknown hypervisor, \"${hypervisor}\" was detected."
echo "Please report this to your support provider."
exit 3
;;
esac
#
# Now let's check for any scripts that other packages may have provided
# to do specific things they need. The scripts must be marked executable
# and have a suffix indicating which hypervisor for which they are to be run.
# Currently that is one of: kvm, lpar, or zvm.
# E.g., 01-test.script.zvm would only be run if the system is a z/VM guest.
#
for script in $(ls /lib/s390-tools/virtsetup/*.${hypervisor} 2>/dev/null)
do if [ -x "${script}" ]; then
echo "Executing ${script}..."
"${script}"
echo "Done."
echo
fi
done
exit 0

92
virtsetup.sh.suse Normal file
View File

@ -0,0 +1,92 @@
#!/bin/sh
#
# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Perform setup tasks based on what hypervisor is in charge.
#
# Source the sysconfig file
if [ -r /etc/sysconfig/virtsetup ]; then
. /etc/sysconfig/virtsetup
else echo "No /etc/sysconfig/virtsetup file was found."
exit 1
fi
#
# Get our hostname
#
my_hostname="$(hostname)"
#
# Find out the hypervisor we're running on/under.
#
hypervisor="$(/usr/bin/systemd-detect-virt)"
case "${hypervisor}" in
zvm)
if [ ! -c /dev/vmcp ]; then
modprobe vmcp
sleep 1
if [ ! -c /dev/vmcp ]; then
echo "Unable to load the vmcp kernel module."
exit 1
fi
fi
echo "The vmcp device driver is ready."
if [ "${ZVM_DETACH_DISKS}" == "yes" ]; then
echo "Detaching devices to prepare for Live Guest Relocation."
/usr/lib/systemd/scripts/detach_disks.sh
fi
if [ "${ZVM_WARN_ABOUT_POSSIBLE_LGR_PROBLEMS}" == yes ]; then
/sbin/lgr_check
fi
;;
none)
hypervisor="lpar"
if [ "${LPAR_SCLP_HOSTNAME}" == "yes" ]; then
# If the sclp_cpi module is already loaded, we have to unload it
# so we can be sure it has the correct system name specified
# when we reload it again.
if grep -qw sclp_cpi /proc/modules 2>/dev/null; then
rmmod sclp_cpi
sleep 1
fi
if grep -qw sclp_cpi /proc/modules 2>/dev/null; then
echo "Unable to unload the sclp_cpi kernel module."
exit 1
fi
echo "Setting the LPAR name via the sclp_cpi module."
modprobe sclp_cpi system_name="$my_hostname"
if ! grep -qw sclp_cpi /proc/modules 2>/dev/null; then
echo "We were unable to load the sclp_cpi module to set the LPAR name."
exit 2
fi
fi
;;
kvm)
;;
*)
echo "An unknown hypervisor, \"${hypervisor}\" was detected."
echo "Please report this to your support provider."
exit 3
;;
esac
#
# Now let's check for any scripts that other packages may have provided
# to do specific things they need. The scripts must be marked executable
# and have a suffix indicating which hypervisor for which they are to be run.
# Currently that is one of: kvm, lpar, or zvm.
# E.g., 01-test.script.zvm would only be run if the system is a z/VM guest.
#
for script in $(ls /lib/s390-tools/virtsetup/*.${hypervisor} 2>/dev/null)
do if [ -x "${script}" ]; then
echo "Executing ${script}..."
"${script}"
echo "Done."
echo
fi
done
exit 0

15
vmlogrdr.service.opensuse Normal file
View File

@ -0,0 +1,15 @@
[Unit]
Description=System startup script for the Linux - z/VM Log reader
After=network-online.target remote-fs.target
Wants=network-online.target remote-fs.target
ConditionPathExists=!/dev/vmlogrdr_LOGREC
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/modprobe vmlogrdr
ExecStop=/usr/sbin/modprobe -r vmlogrdr
[Install]
WantedBy=default.target

15
vmlogrdr.service.suse Normal file
View File

@ -0,0 +1,15 @@
[Unit]
Description=System startup script for the Linux - z/VM Log reader
After=network-online.target remote-fs.target
Wants=network-online.target remote-fs.target
ConditionPathExists=!/dev/vmlogrdr_LOGREC
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/modprobe vmlogrdr
ExecStop=/sbin/modprobe -r vmlogrdr
[Install]
WantedBy=default.target

181
xpram Normal file
View File

@ -0,0 +1,181 @@
#! /bin/sh
# Copyright (c) 2004 SUSE LINUX AG Nuernberg, Germany.
#
# Submit feedback to http://www.suse.de/feedback/
#
# System startup script for XPRAM device driver
XPRAM_CONFIG_FILE=/etc/sysconfig/xpram
read_config_file() {
if [ config_read = 1 ]; then
return 0
fi
file=$XPRAM_CONFIG_FILE
if [ -s "$file" ]; then
source $file
config_read=1
else
echo -ne "Cannot read $file: empty or nonexistant! "
# Means not configured:
return 6
fi
}
prepare_xpram() {
if [ -z "$XPRAM_MNTPATH" -o -z "$XPRAM_DEVNODE" ]; then
echo -n "Cannot mkfs/mount XPRAM: Missing parameters! "
exit 6
fi
grep -q $XPRAM_DEVNODE /proc/mounts 2>&1 > /dev/null
if [ $? -eq 0 ] ; then
echo -n "$service: $XPRAM_DEVNODE already mounted! "
return
fi
current_fstype=`vol_id -t $XPRAM_DEVNODE 2> /dev/null`
if [ $? -ne 0 -o "$XPRAM_FORCE" = "yes" ]
then
# Does not contain a valid filesystem/swap space
if [ "$XPRAM_FSTYPE" = swap ]
then
mkswap $XPRAM_DEVNODE
else
mkfs -t "$XPRAM_FSTYPE" -b 4096 "$XPRAM_DEVNODE"
fi
sleep 1 # workaround
current_fstype=$XPRAM_FSTYPE
fi
if [ ! "$current_fstype" = "$XPRAM_FSTYPE" ]
then
echo
echo -n "Warning: current filessystem and configured filesystem are not the same!"
exit 6
fi
if [ "$XPRAM_FSTYPE" = swap ]
then
if [ "$XPRAM_SWAP_PRI" = "" ]
then
swapon $XPRAM_DEVNODE
else
swapon -p $XPRAM_SWAP_PRI $XPRAM_DEVNODE
fi
else
if [ ! -d "$XPRAM_MNTPATH" ]
then
mkdir -p "$XPRAM_MNTPATH"
fi
mount "$XPRAM_DEVNODE" "$XPRAM_MNTPATH"
if [ $? -ne 0 ]
then
echo -n "Mount failed with error code $?"
exit 6
fi
fi
}
# Return values acc. to LSB for all commands but status:
# 0 - success
# 1 - generic or unspecified error
# 2 - invalid or excess argument(s)
# 3 - unimplemented feature (e.g. "reload")
# 4 - insufficient privilege
# 5 - program is not installed
# 6 - program is not configured
# 7 - program is not running
#
# Note that starting an already running service, stopping
# or restarting a not-running service as well as the restart
# with force-reload (in case signalling is not supported) are
# considered a success.
check_config () {
if [ -z "$XPRAM_MODULE" ]; then
echo -n "$file: parameters XPRAM_MODULE missing! "
exit 6
fi
}
quit_disabled() {
if [ "$XPRAM_START" != "yes" ]; then
# Config file exists but xpram not enabled, do not complain,
# but note with exit status 6 that we are not configured.
echo "xpram not enabled"
exit 0
fi
}
service="xpram"
case "$1" in
start)
# Read in configuration
read_config_file || exit 6
quit_disabled
check_config
echo -n "Creating $service device "
modprobe "$XPRAM_MODULE"
if [ $? -ne 0 ]; then
echo -n "- failed to load $XPRAM_MODULE "
exit 1
else
prepare_xpram
fi
;;
stop)
# Read in configuration
read_config_file || exit 6
# check_enabled
# quit_disabled
echo -n "Removing $service device "
check_config
if [ "$XPRAM_DEVNODE" ]; then
if grep -q $XPRAM_DEVNODE /proc/mounts; then
umount $XPRAM_DEVNODE
fi
if swapon -s | grep -q $XPRAM_DEVNODE; then
swapoff $XPRAM_DEVNODE
fi
fi
if grep -q "$XPRAM_MODULE" /proc/modules; then
rmmod "$XPRAM_MODULE"
else
exit 7
fi
;;
status)
echo -n "Checking $service "
# Status has a slightly different meaning for the status command:
# 0 - service running
# 1 - service dead, but /var/run/ pid file exists
# 3 - service not running
# Read in configuration
read_config_file || exit 3
check_config
lsmod | grep -q $XPRAM_MODULE
if [ $? -eq 0 ]; then
if [ "$XPRAM_DEVNODE" ]; then
if ! grep -q $XPRAM_DEVNODE /proc/mounts && ! swapon -s | grep -q $XPRAM_DEVNODE; then
xpram_result=3
echo -n "loaded, but $XPRAM_DEVNODE not used"
exit 3
fi
fi
else
exit 3
fi
;;
esac

18
xpram.service Normal file
View File

@ -0,0 +1,18 @@
[Unit]
Description=Linux - z/VM Monitor Stream
After=network-online.target remote-fs.target
Wants=network-online.target remote-fs.target
ConditionPathExists=/proc/sys/appldata/interval
ConditionPathExists=!/var/lock/appldata
[Service]
Type=oneshot
RemainAfterExit=yes
SuccessExitStatus=3
ExecStart=/usr/lib/systemd/scripts/xpram start
ExecStartPost=/usr/lib/systemd/scripts/xpram status
ExecStop=/usr/lib/systemd/scripts/xpram stop
[Install]
WantedBy=default.target

73
zfcp_disk_configure Normal file
View File

@ -0,0 +1,73 @@
#!/bin/sh
#
# zfcp_disk_configure
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Configures a zfcp-attached Logical Unit by calling the IBM-provided chzdev command.
# Whereas this script used to validate the parameters provided to it,
# we now rely on chzdev to do that instead. The script is intended only
# as a "translation layer" to provide backward compatability for older
# scripts and tools that invoke it.
#
# Usage:
# zfcp_disk_configure <ccwid> <wwpn> <lun> <online>
#
# ccwid = x.y.ssss where
# x is always 0 until IBM creates something that uses that number
# y is the subchannel set ID (SSID). Most often
# this is 0, but it could be non-zero
# ssss is the four digit device address of the subchannel, in
# hexidecimal, with leading zeros.
# online = 0 to take the device offline
# 1 to bring the device online
#
# Return values:
# Return codes are determined by the chzdev command.
#
mesg () {
echo "$@"
}
debug_mesg () {
case "${DEBUG}" in
yes) mesg "$@" ;;
*) ;;
esac
}
usage(){
echo "Usage: ${0} <ccwid> <wwpn> <lun> <online>"
echo " ccwid = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the subchannel set ID (SSID). Most often"
echo " this is 0, but it could be non-zero"
echo " ssss is the four digit device address of the subchannel, in"
echo " hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
}
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
CCW_CHAN_ID=${1}
FCP_WWPN="${2}"
FCP_LUN="${3}"
ON_OFF=${4}
# normalise to lower case
FCP_WWPN=$(echo ${FCP_WWPN} | tr "A-Z" "a-z")
FCP_LUN=$(echo ${FCP_LUN} | tr "A-Z" "a-z")
if [ "${ON_OFF}" == 0 ]; then
debug_mesg "chzdev -d zfcp-lun --no-root-update ${CCW_CHAN_ID}:${FCP_WWPN}:${FCP_LUN}"
chzdev -d zfcp-lun --no-root-update ${CCW_CHAN_ID}:${FCP_WWPN}:${FCP_LUN}
elif [ "${ON_OFF}" == 1 ]; then
debug_mesg "chzdev -e zfcp-lun --no-root-update ${CCW_CHAN_ID}:${FCP_WWPN}:${FCP_LUN}"
chzdev -e zfcp-lun --no-root-update ${CCW_CHAN_ID}:${FCP_WWPN}:${FCP_LUN}
else mesg "You must specify a 0 or a 1 for the online/offline attribute."
usage
exit 1
fi

46
zfcp_disk_configure.8 Normal file
View File

@ -0,0 +1,46 @@
.TH zfcp_disk_configure "8" "February 2013" "s390-tools"
.SH NAME
zfcp_disk_configure \- Configures or deconfigures a zfcp-attached SCSI Logical Unit (LU).
.SH SYNOPSIS
.B zfcp_disk_configure ccwid wwpn lun online
.SH DESCRIPTION
.B zfcp_disk_configure
is intended to make it easy to persistently add and remove zfcp-attached SCSI Logical Units. In addition to bringing the LU online or offline, it will also create or delete the necessary udev rules for the LU.
.SH PARAMETERS
.IP ccwid
The device number of the zFCP adapter. Takes the form x.y.ssss where
.RS
.B x
is always 0 until IBM creates something that uses that number.
.RE
.RS
.B y
is the subchannel set ID (SSID). Most often this is 0, but it could be non-zero.
.RE
.RS
.B ssss
is the four digit device address of the subchannel, in hexidecimal, with leading zeros. If entered in upper/mixed case, this is automatically converted to lower case.
.RE
.IP wwpn
Is the World Wide Port Number of the storage array in which the LUN resides. This will be a 16 digit hexidecimal number of the form 0x0123456789abcdef. You must obtain this number from the administrator of the storage array.
.IP lun
Is the Logical Unit Number of the specific disk in the storage array. This will also be a 16 digit hexidecimal number of the form 0x0123456789abcdef. You must obtain this number from the administrator of the storage array. Be careful in that some storage array administrator interfaces disply the LUN in decimal, and must be converted to hexidecimal to be used in this command.
.IP online
Either a literal 1 to attach the LU or a literal 0 to detach the LU.
.SH FILES
Please see the documentation of
.B chzdev.
.RE
.SH ENVIRONMENT
.IP DEBUG
If set to "yes" some minimal debugging information is output during execution.
.SH DIAGNOSTICS
Messages and return codes are determined by the
.B chzdev
command.
If environment variable DEBUG is set to "yes," it shows the command line of the invoked
.B chzdev.
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.
.SH SEE ALSO
zfcp_host_configure(8), zfcp_san_disc(8), chzdev(8)

82
zfcp_host_configure Normal file
View File

@ -0,0 +1,82 @@
#!/bin/sh
#
# zfcp_host_configure
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# Configures a zfcp host adapter by calling the IBM-provided chzdev command.
# Whereas this script used to validate the parameters provided to it,
# we now rely on chzdev to do that instead. The script is intended only
# as a "translation layer" to provide backward compatability for older
# scripts and tools that invoke it.
#
#
# Usage:
# zfcp_host_configure <ccwid> <online>
#
# ccwid = x.y.ssss where
# x is always 0 until IBM creates something that uses that number
# y is the subchannel set ID (SSID). Most often
# this is 0, but it could be non-zero
# ssss is the four digit device address of the subchannel, in
# hexidecimal, with leading zeros.
# online = 0 to take the device offline
# 1 to bring the device online
#
# Return codes
# Return codes are determined by the chzdev command.
#
mesg () {
echo "$@"
}
debug_mesg () {
case "${DEBUG}" in
yes) mesg "$@" ;;
*) ;;
esac
}
usage(){
echo "Usage: ${0} <ccwid> <online>"
echo " ccwid = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the subchannel set ID (SSID). Most often"
echo " this is 0, but it could be non-zero"
echo " ssss is the four digit device address of the subchannel, in"
echo " hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
}
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATE=$(date)
CCW_CHAN_ID=${1}
ON_OFF=${2}
if [ -z "${CCW_CHAN_ID}" ] || [ -z "${ON_OFF}" ]; then
mesg "You didn't specify all the needed parameters."
usage
exit 1
fi
if [ "${ON_OFF}" == 0 ]; then
debug_mesg "chzdev -d zfcp-host --no-root-update ${CCW_CHAN_ID}"
chzdev -d zfcp-host --no-root-update ${CCW_CHAN_ID}
elif [ "${ON_OFF}" == 1 ]; then
debug_mesg "chzdev -e zfcp-host --no-root-update ${CCW_CHAN_ID}"
chzdev -e zfcp-host --no-root-update ${CCW_CHAN_ID}
else mesg "You must specify a 0 or a 1 for the online/offline attribute."
usage
exit 1
fi
RC=${?}
if [ ${RC} -ne 0 ]; then
exit ${RC}
fi

42
zfcp_host_configure.8 Normal file
View File

@ -0,0 +1,42 @@
.TH zfcp_host_configure "8" "February 2013" "s390-tools"
.SH NAME
zfcp_host_configure \- Configures or deconfigures a zFCP host bus adapter (HBA).
.SH SYNOPSIS
.B zfcp_host_configure ccwid online
.SH DESCRIPTION
.B zfcp_host_configure
is intended to make it easy to persistently add and remove IBM zFCP adapters. In addition to bringing the adapter online or offline, it will also create or delete the necessary udev rules for the adapter.
.SH PARAMETERS
.IP ccwid
The device number of the zFCP adapter. Takes the form x.y.ssss where
.RS
.B x
is always 0 until IBM creates something that uses that number.
.RE
.RS
.B y
is the subchannel set ID (SSID). Most often this is 0, but it could be non-zero.
.RE
.RS
.B ssss
is the four digit device address of the subchannel, in hexidecimal, with leading zeros. If entered in upper/mixed case, this is automatically converted to lower case.
.RE
.IP online
Either a literal 1 to bring the adapter online or a literal 0 to take it offline
.SH FILES
Please see the documentation of
.B chzdev.
.RE
.SH ENVIRONMENT
.IP DEBUG
If set to "yes" some minimal debugging information is output during execution.
.SH DIAGNOSTICS
Messages and return codes are determined by the
.B chzdev
command.
If environment variable DEBUG is set to "yes," it shows the command line of the invoked
.B chzdev.
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.
.SH SEE ALSO
zfcp_disk_configure(8), zfcp_san_disc(8), chzdev(8)

330
zfcp_san_disc Normal file
View File

@ -0,0 +1,330 @@
#!/bin/bash
#
# zfcp_san_disc
#
# Outputs a list of zFCP WWPNs or LUNs
#
# Usage:
# zfcp_san_disc [-h | -W | -L -p <WWPN> ] -b <BUS_ID>
#
# Return codes
# 1 zFCP sysfs directory not available
# 2 Invalid command line parameter
# 3 Too many commands used
# 4 Error retrieving HBA list
# 5 Bus ID not found
# 6 Error retrieving Port list
# 7 WWPN not found
# 8 Bus ID sysfs directory not available
# 9 WWPN sysfs directory not available/unable to add port to Bus ID
# 10 Error retrieving LUN list
# 11 HBA API device not available
#
START_DIR=`pwd`
SCRIPT_NAME=`basename $0`
cd `dirname $0`
SCRIPT_DIR=`pwd`
cd "${START_DIR}"
FCP_SYS_DIR='/sys/bus/ccw/drivers/zfcp'
# Commands available
LIST_WWPN='-W'
LIST_LUN='-L'
COMMAND=''
BUSID=''
WWPN=''
echo_err()
{
echo "$SCRIPT_NAME: $1" 1>&2
}
usage()
{
echo "$0 [-h | $LIST_WWPN | $LIST_LUN -p <WWPN>] -b <BUS_ID>" 1>&2
echo 1>&2
echo "Commands:" 1>&2
echo " $LIST_WWPN List WWPNs for the given BUS_ID" 1>&2
echo " $LIST_LUN List LUNs for the given BUS_ID and WWPN" 1>&2
echo " -h This usage information" 1>&2
echo "Options:" 1>&2
echo " -b BUSID Bus ID to use for listing" 1>&2
echo " -p WWPN WWPN to use for listing" 1>&2
}
list_lun()
{
local PRINT_WWPN
local BUSID_DIR
local WWPN_DIR
local ADDED_PORT
}
deactivate()
{
local ccw=$1
echo 0 > /sys/bus/ccw/devices/$ccw/online
}
lun_remove()
{
local syspath=$1
local lun=$2
echo "$lun" > $syspath/unit_remove
}
sg_remove()
{
local sg=$1
local sgnum
sgnum=${sg#/dev/sg}
: deactivate /sys/class/scsi_generic/sg$sgnum/device/delete
echo 1 > /sys/class/scsi_generic/sg$sgnum/device/delete
udevadm settle
}
while [ $# -gt 0 ]
do
case "$1" in
-b* )
if [ "$1" == "-b" ]
then
shift
BUSID="$1"
else
BUSID="${1:2}"
fi
BUSID=`echo $BUSID | tr A-F a-f`
;;
-p* )
if [ "$1" == "-p" ]
then
shift
WWPN="$1"
else
WWPN="${1:2}"
fi
WWPN=`echo $WWPN | tr A-FX a-fx`
;;
"$LIST_WWPN"|"$LIST_LUN" )
if [ -z "$COMMAND" -o "$1" == "$COMMAND" ]
then
COMMAND=$1
else
echo_err "You have already specified the $COMMAND command, and cannot use the $1 command also."
exit 3
fi
;;
-h )
usage
exit 0
;;
* )
usage
echo_err "Unknown command line parameter : $1"
exit 2
;;
esac
shift
done
if [ -z "$BUSID" ] ; then
echo_err "No bus ID given"
exit 2
fi
if [ -z "$COMMAND" ] ; then
echo_err "Please specify either -W or -L"
exit 2
fi
if [ ! -d /sys/bus/ccw/devices/$BUSID ] ; then
echo_err "Unknown bus ID $BUSID"
exit 2
fi
read devtype < /sys/bus/ccw/devices/$BUSID/devtype
read cutype < /sys/bus/ccw/devices/$BUSID/cutype
if [ "$cutype" != "1731/03" ] ; then
echo_err "Bus ID $BUSID is not an zfcp adapter"
exit 2
fi
if [ "$devtype" != "1732/03" -a "$devtype" != "1732/04" ] ; then
echo_err "Bus ID $BUSID is not an zfcp adapter"
exit 2
fi
# Now we're sure we're dealing with zfcp devices
if [ ! -d "$FCP_SYS_DIR" ] ; then
modprobe zfcp
fi
[ "$COMMAND" == "$LIST_LUN" -a -z "$WWPN" ] && usage && exit 2
read online < /sys/bus/ccw/devices/$BUSID/online
if [ "$online" != 1 ] ; then
# Activate adapter
echo 1 > /sys/bus/ccw/devices/$BUSID/online
read online < /sys/bus/ccw/devices/$BUSID/online
if [ "$online" != 1 ] ; then
echo_err "Cannot activate zfcp adapter at $BUSID"
exit 2
fi
trapcmd="deactivate $BUSID"
trap "$trapcmd" EXIT
fi
for loop in 1 2 3 4 5 ; do
read status < /sys/bus/ccw/devices/$BUSID/status
(( $status & 0x10000000 )) && break;
done
read wwpn_status < /sys/bus/ccw/devices/$BUSID/status
if !(( $wwpn_status & 0x10000000 )) ; then
echo_err "Adapter activation failed, status $wwpn_status"
exit 3
fi
for host in /sys/bus/ccw/devices/$BUSID/host* ; do
if [ -d $host ] ; then
hba_num=${host##*host}
fi
done
if [ -z "$hba_num" ] ; then
echo_err "No SCSI host allocated"
exit 3
fi
if [ "$COMMAND" == "$LIST_WWPN" ]
then
for PRINT_WWPN in /sys/bus/ccw/devices/$BUSID/0x*
do
test -d $PRINT_WWPN && echo ${PRINT_WWPN##*/}
done
exit 0
elif [ "$COMMAND" != "$LIST_LUN" ]
then
exit 1
fi
ERR=0
read allow_lun_scan < /sys/module/zfcp/parameters/allow_lun_scan
if [ "$allow_lun_scan" = "Y" ] ; then
read port_type < /sys/class/fc_host/host${hba_num}/port_type
if [ "$port_type" = "NPIV VPORT" ] ; then
skip_activation=1
fi
fi
if [ -z "$skip_activation" ] ; then
WWPN_DIR=/sys/bus/ccw/devices/$BUSID/$WWPN
if [ ! -d "${WWPN_DIR}" ]
then
echo_err "port $WWPN not found on zfcp $BUSID"
exit 9
fi
# Activate WLUN
if [ ! -d $WWPN_DIR/0xc101000000000000 ] ; then
echo 0xc101000000000000 > $WWPN_DIR/unit_add
orig_trapcmd="$trapcmd"
trapcmd="lun_remove $WWPN_DIR 0xc101000000000000; $trapcmd"
trap "$trapcmd" EXIT
activated=1
# Wait for udev to catch up
udevadm settle
sleep 1
fi
# Find corresponding sg device
sgdev=$(lsscsi -t -g $hba_num:-:-:49409 | sed -n "s/.* fc:$WWPN.* \(\/dev\/sg[0-9]*\)[[:blank:]]*$/\1/p")
if [ -c "$sgdev" ] ; then
if sg_luns $sgdev > /dev/null 2>&1 ; then
LUN_LIST=`sg_luns $sgdev | sed -n 's/^ \(.*\)/\1/p'`
trapcmd="sg_remove $sgdev; $trapcmd"
trap "$trapcmd" EXIT
wlun=1
else
wlun=
fi
fi
if [ -z "$wlun" ] ; then
if [ -n "$activated" ] ; then
trapcmd=$orig_trapcmd
trap "$trapcmd" EXIT
lun_remove $WWPN_DIR 0xc101000000000000
activated=
fi
# Activate LUN 0
if [ ! -d $WWPN_DIR/0x0000000000000000 ] ; then
echo 0 > $WWPN_DIR/unit_add
orig_trapcmd=$trapcmd
trapcmd="lun_remove $WWPN_DIR 0x0000000000000000; $trapcmd"
trap "$trapcmd" EXIT
activated=1
# Wait for udev to catch up
udevadm settle
sleep 1
fi
# Find corresponding sg device
sgdev=$(lsscsi -t -g $hba_num:-:-:0 | sed -n "s/.* fc:$WWPN.* \(\/dev\/sg[^[:blank:]]*\)[[:blank:]]*$/\1/p")
if [ -c "$sgdev" ] ; then
if sg_luns $sgdev > /dev/null 2>&1 ; then
LUN_LIST=`sg_luns $sgdev | sed -n 's/^ \(.*\)/\1/p'`
fi
if [ -n "$activated" ] ; then
trapcmd="sg_remove $sgdev; $trapcmd"
trap "$trapcmd" EXIT
fi
else
echo_err "Unable to activate LUN 0"
trap "$trapcmd" EXIT
lun_remove $WWPN_DIR 0x0000000000000000
activated=
sgdev=
ERR=10
fi
fi
for LUN in $LUN_LIST ; do
echo 0x$LUN
done
exit $ERR
else
for loop in 1 2 3 4 5 ; do
if [ -n "$(ls -d /sys/class/fc_remote_ports/rport-${hba_num}:* 2>/dev/null)" ] ; then
break
else
sleep 1
fi
done
if [ -z "$(ls -d /sys/class/fc_remote_ports/rport-${hba_num}:* 2>/dev/null)" ]; then
echo "The remote Fiber Channel port has not become available. Exiting"
exit 1
fi
for rport in /sys/class/fc_remote_ports/rport-${hba_num}:* ; do
[ -f ${rport}/port_name ] || continue
read port_name < ${rport}/port_name
if [ "$port_name" = "$WWPN" ] ; then
for t in ${rport}/device/target* ; do
[ -f ${t}/uevent ] || continue
targetid=${t#*target}
targetid=${targetid##*:}
break
done
fi
done
lsscsi -xx ${hba_num}:0:${targetid}:- | sed -n "s/\[${hba_num}:0:${targetid}:\(0x[0-9a-f]*\)\].*/\1/p"
fi

31
zipl.conf Normal file
View File

@ -0,0 +1,31 @@
#
# Example zipl.conf file
#
[defaultboot]
default = linux
[linux]
target = "/boot/zipl"
image = "/boot/kernel/image"
#ramdisk=/boot/initrd
parameters = "root=/dev/ram0 ro"
[customized]
target = "/boot/zipl"
image = "/boot/kernel/image-customized"
parmfile = "/boot/kernel/parmfile-customized"
[dumpdasd]
target = "/boot/zipl"
dumpto = "/dev/dasd??"
[dumpzfcp]
target = "/boot/zipl"
dumptofs = "/dev/zfcp??"
:menu1
target = "/boot/zipl"
1 = linux
2 = customized
default = 1

528
zpxe.rexx Normal file
View File

@ -0,0 +1,528 @@
/* zPXE: REXX PXE Client for System z
zPXE is a PXE client used with Cobbler or a just a plain TFTP server.
It must be run under z/VM. zPXE uses TFTP to first download a
user-specific profile (if one exists), or a list of available profiles.
From the profile a specific kernel, initial RAMdisk, and PARM file are
then downloaded and these files are then punched to start the install
process.
zPXE does not require a writeable 191 A disk. Files are downloaded to a
temporary disk (VDISK).
zPXE can also IPL from a DASD volume by default. You can specify the
default DASD device in ZPXE CONF, as well as the hostname or IP address
of the Cobbler or TFTP server.
---
Copyright 2006-2009, Red Hat, Inc
Brad Hinson <bhinson@redhat.com>
Copyright 2012, 2017, SUSE Linux,
Mark Post <mpost@suse.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
/* Set the default environment for "safety" reasons. */
ADDRESS COMMAND
/* Save the value of the trace state */
tvar_o=trace()
tvar_c=tvar_o
/* Was this script invoked with "debug" as one of the parameters? */
debug=0
if arg() then
do
parse upper arg uparg
do sub=1 to words(uparg)
if word(uparg,sub) = "DEBUG" then
do
debug=1;
trace i;
tvar_c=trace()
end;
else do /* This is a do/end in case we want to add to it later */
trace e
tvar_c=trace()
end
end
end
/* Set some defaults */
/* These values are intended to be modified by the site using this */
/* script to match their environment. */
userid=''
server=''
iplDisk=''
server_def = 'internal.tftp.server' /* define default TFTP server */
iplDisk_def = '150' /* define default IPL DASD */
FM='T' /* Default file mode is T */
profilelist = 'PROFILE LIST' FM /* Disk will be accessed as FM later */
profiledetail = 'PROFILE DETAIL' FM
zpxeparm = 'ZPXE PARM' FM
zpxeconf = 'ZPXE CONF' FM
config = 'ZPXE CONF A'
seconds=10 /* The default amount of time to wait for console input */
workDiskType='VFB-512'
workDiskSize=200000 /* This is approximately 97MB of space. */
/* For TDISK instead of VDISK, comment out the previous two lines and */
/* uncomment the following two lines.*/
/* workDisk='T3390' */
/* workDiskSize=138 */
/* Make it possible to interrupt zPXE and to enter CMS no matter how
the guest was started, if there is a system-specific profile
or not, etc.
*/
if debug then say 'Debugging, so we will skip the wait and just run.'
else do
say
say 'Enter a non-blank character and ENTER (or two ENTERs)',
'within' seconds 'seconds to interrupt zPXE.'
ADDRESS CMS 'WAKEUP +00:'seconds '(CONS'
/* Check for the interrupt code */
if rc = 6 then do
say 'Interrupt received: exiting to CMS...'
ADDRESS CMS 'DESBUF' /* Clear the stack */
exit
end
end
/* For translating strings to lowercase */
lower = xrange('a','i')xrange('j','r')xrange('s','z')
upper = xrange('A','I')xrange('J','R')xrange('S','Z')
/* Query user ID. This is used to determine:
1. Whether a user-specific PXE profile exists.
2. Whether user is disconnected.
The logic that gets followed will vary based on the results.
*/
ADDRESS CMS 'QUERY USER' userid() '(STACK'
parse pull userid_def dash dsc
if dsc = 'DSC' then disconnected=1 /* user is disconnected */
else disconnected=0
/* Yeah, this call to translate looks backward, but it's not. Sorry. */
userid_def = translate(userid_def, lower, upper)
/* Useful settings normally found in PROFILE EXEC */
'CP SET RUN ON'
'CP SET PF11 RETRIEVE FORWARD'
'CP SET PF12 RETRIEVE'
/* Useful setting for a script that may run unattended */
'CP TERM HOLD OFF'
/* We want to have a way to figure out what went wrong if something
isn't working. */
'CP SPOOL CONSOLE STOP CLOSE' /* Close any existing spooled console. */
'CP SPOOL CONSOLE START' /* Start spooling the console for this run. */
if \ debug then ADDRESS CMS 'VMFCLEAR' /* clear screen */
/* The following two commands that were in the original script are */
/* almost certainly not going to work for anyone that only has CP */
/* privilege class G */
/* 'set vdisk syslim infinite' */
/* 'set vdisk userlim infinite' */
/* Define a temporary disk to store files and CMS FORMAT it */
/* If your site doesn't allow this, but does allow TDISKs, change the */
/* DEFINE command to T3390 instead */
'CP SET EMSG OFF'
if \ debug then trace off
'CP DETACH FFFF' /* detach ffff if present */
trace value tvar_c
'CP SET EMSG ON'
'CP DEFINE' workDiskType' AS FFFF' workDiskSize
queue '1'
queue 'tmpdsk'
if \ debug then /* If debug was not specified, then */
ADDRESS CMS 'set cmstype ht' /* suppress format output */
ADDRESS CMS 'format ffff' FM /* format VDISK as file mode FM */
ADDRESS CMS 'set cmstype rt' /* Resume seeing command output */
say 'DASD FFFF has been CMS formatted'
/* Check for the ZPXE CONF A config file and use whatever is there in
preference over the defaults in this script */
call GetZPXECONF
/* For any values not found in ZPXE CONF A, or if it doesn't exist, use
the default values specified in this script. */
if server = '' then do
say 'Setting TFTP server to 'server_def
server = server_def
end
if iplDisk = '' then do
say 'Setting IPL disk to default of 'iplDisk_def
iplDisk = iplDisk_def
end
if userid = '' then do
say 'Setting userid to default of 'userid_def
userid = userid_def
end
/* Link to TCPMAINT's 592 disk for access to the TFTP command */
say
ADDRESS CMS 'exec vmlink tcpmaint 592'
say
say 'Connecting to server 'server /* print server name */
/* Check whether a user-specific PXE profile exists. */
call GetTFTP '/s390x/s_'userid 'profile.detail.'FM
if lines(profiledetail) > 0 then call ProcessUserProfile
else do /* no user-specific profile was found */
say 'No profile found for' userid
if disconnected then do /* user is disconnected */
ADDRESS CMS 'release' FM '(detach'
ADDRESS CMS 'exec vmlink tcpmaint 592 <detach>'
say 'User is disconnected. Booting from DASD 'iplDisk'...'
'CP IPL' iplDisk
end
else call ProcessGenericProfiles /* user is interactive -> prompt */
end /* no user-specific profile was found */
trace value tvar_o
exit
/* */
/* Subroutines called from the main script */
/* */
/* Procedure GetZPXECONF
*/
GetZPXECONF:
if lines(config) > 0 then do
say config "was found"
do while lines(config) > 0
inputline = linein(config)
parse upper var inputline keyword value .
select
when (keyword = 'HOST') then do /* line is server hostname/IP */
server = value
if server = '' then say config "didn't have an IP address for",
"the TFTP server."
else say ' Setting TFTP server to 'server
end
when (keyword = 'IPLDISK') then do /* line is default IPL disk */
iplDisk = value
if iplDisk = '' then say config "didn't have an IPL Disk parm."
else say ' Setting IPL disk to 'iplDisk
end
otherwise do /* line is userid to use instead of the default */
userid = translate(keyword,lower,upper) /* Still not backward */
say ' Setting userid to 'userid
end
end /* select */
end /* do while lines(config) > 0 */
end /* if lines(config) > 0 */
return /* GetZPXECONF */
/* Procedure ProcessUserProfile
*/
ProcessUserProfile:
say 'Profile for 'userid' found'
say
bootRc = ParseSystemRecord() /* parse file for boot action */
if bootRc = 0 then do
say 'The profile said we should boot from local disk.'
ADDRESS CMS 'release' FM '(detach'
ADDRESS CMS 'exec vmlink tcpmaint 592 <detach>'
say 'IPLing from' iplDisk
'CP IPL' iplDisk /* boot from default DASD */
end /* if bootRc = 0 */
else do /* The profile should contain pointers to kernel, etc.*/
abort=0
/* Get the user PARM file that contains network info */
say 'Downloading parameter file [/s390x/s_'userid'_parm]...'
call GetTFTP '/s390x/s_'userid'_parm' 'zpxe.parm.'FM
if CheckDownload('s_'userid'_parm' zpxeparm) <> 0 then
abort=1
/* Get the user CONF file that currently isn't used for anything */
say 'Downloading conf file [/s390x/s_'userid'_conf]...'
call GetTFTP '/s390x/s_'userid'_conf' 'zpxe.conf.'FM
if CheckDownload('s_'userid'_conf' zpxeconf) <> 0 then
abort=1
if abort then do
say 'Aborting PXE boot.'
exit 99
end
call DownloadBinaries /* download kernel and initrd */
say 'Starting install...'
say
call PunchFiles /* punch files to begin install */
exit
end /* he profile should contain pointers to kernel, etc */
/* ProcessGenericProfiles
*/
ProcessGenericProfiles:
/* Download the list of generic profiles available */
say 'Downloading the profile list [/s390x/profile_list]...'
call GetTFTP '/s390x/profile_list' 'profile.list.'FM
if CheckDownload('profile_list' profilelist) <> 0 then do
say '** **'
say '** No profile list found **'
say '** Possible error connecting to server? **'
say '** **'
exit 99
end
/* Display a menu of the generic profiles */
say
say 'zPXE MENU'
say '---------'
/* Display one profile per line */
do count = 1 by 1 while lines(profilelist) > 0
inputline = linein(profilelist)
parse var inputline profile.count
say count'. 'profile.count
end
/* Add two non-profile selections to the menu */
say count'. Don''t continue, exit to CMS'
say
say
say 'Enter Choice -->'
say 'or press <Enter> to boot from disk [DASD 'iplDisk']'
parse pull answer .
select
when answer = count then do /* Exit to CMS was selected */
say
say 'Exiting to CMS...'
exit
end
when answer = '' then do /* IPL from default disk */
ADDRESS CMS 'release' FM '(detach'
ADDRESS CMS 'exec vmlink tcpmaint 592 <detach>'
say 'Booting from DASD 'iplDisk'...'
'CP IPL' iplDisk
end
when (answer > 0) & (answer < count) then do /* valid response */
abort=0
say 'Downloading generic profile [/s390x/p_'profile.answer']...'
call GetTFTP '/s390x/p_'profile.answer 'profile.detail.'FM
if CheckDownload('p_'profile.answer profiledetail) <> 0 then
abort=1
say 'Downloading generic parameter file',
'[/s390x/p_'profile.answer'_parm]...'
call GetTFTP '/s390x/p_'profile.answer'_parm' 'zpxe.parm.'FM
if CheckDownload('p_'profile.answer'_parm' zpxeparm) <> 0 then
abort=1
say 'Downloading generic conf file',
'[/s390x/p_'profile.answer'_conf]...'
call GetTFTP '/s390x/p_'profile.answer'_conf' 'zpxe.conf.'FM
if CheckDownload('p_'profile.answer'_conf' zpxeconf) <> 0 then
abort=1
if abort then do
say 'Aborting PXE boot.'
exit 99
end
/* We have to add the HostIP parameter to the parm file, since that is
going to vary for each guest, so we can't hard-code it in the generic
profiles. We use the numeric part of the guest name, which starts in
column 6, after "LINUX". But we have to watch out for leading zeros,
since that will appear as an octal number to Linux. So, we use the
fact that Rexx/Regina doesn't care about leading zeros, but will
remove them when used in an arithmetic statement, such as follows. */
lastoctet=substr(userid,6)
lastoctet=lastoctet+0 /* Adding a zero won't change the value */
hostipparm=' HostIP=10.121.157.'lastoctet
call lineout zpxeparm, hostipparm
call lineout zpxeparm /* close the output file */
if \ debug then ADDRESS CMS 'VMFCLEAR' /* clear screen */
say
say 'Using profile 'answer' ['profile.answer']'
say
call DownloadBinaries /* download kernel and initrd */
say 'Starting install...'
say
call PunchFiles
end /* valid response */
otherwise do /* The user entered something that wasn't in the list */
say 'Invalid choice, exiting to CMS...'
exit
end
end /* Select */
/* Procedure GetTFTP
Use CMS TFTP client to download files
path: remote file location
filename: local file name
transfermode [optional]: 'ascii' or 'octet'
*/
GetTFTP:
parse arg path filename transfermode
if transfermode <> '' then
queue 'mode' transfermode
queue 'get 'path filename
queue 'quit'
if \ debug then
ADDRESS CMS 'set cmstype ht' /* suppress TFTP output */
ADDRESS CMS 'tftp' server
ADDRESS CMS 'set cmstype rt'
return /* GetTFTP */
/* Procedure CheckDownload
TFTP is dumb, so you can't ever tell if a file was actually retrieved
or not from the return code.
path: The filename (including path) that was to be retrieved
via TFTP
filename: The local CMS filename that should have received it.
*/
CheckDownload:
parse arg path filename
if lines(filename) = 0 then do
say 'The' path 'file was not successfully retrieved'
return 99
end
else return 0
/* End CheckDownload */
/* Procedure DownloadBinaries
Download kernel and initial RAMdisk. Convert both
to fixed record length 80.
*/
DownloadBinaries:
inputline = linein(profiledetail) /* first line is kernel */
parse var inputline kernelpath
if kernelpath = '' then do
say 'The path to the kernel is null. Aborting...'
exit 99
end
say 'Downloading kernel ['kernelpath']...'
call GetTFTP kernelpath 'kernel.img.'FM octet
if CheckDownload(kernelpath kernel img FM) <> 0 then do
say 'Aborting PXE boot.'
exit 99
end
inputline = linein(profiledetail) /* second line is initrd */
parse var inputline initrdpath
if initrdpath = '' then do
say 'The path to the initrd is null. Aborting...'
exit 99
end
say 'Downloading initrd ['initrdpath']...'
call GetTFTP initrdpath 'initrd.img.'FM octet
if CheckDownload(initrdpath initrd img FM) <> 0 then do
say 'Aborting PXE boot.'
exit 99
end
inputline = linein(profiledetail) /* third line is kernel parms */
parse var inputline kparms
if kparms <> '' then do /* If there are parms, add them to the end */
call lineout zpxeparm, kparms /* add ks line to end of parm */
call lineout zpxeparm /* close file */
end
/* Convert to fixed record length since they're going to be run
through the virtual card reader. */
ADDRESS CMS 'pipe < KERNEL IMG 'FM' | fblock 80 00 | > KERNEL IMG' FM
ADDRESS CMS 'pipe < INITRD IMG 'FM' | fblock 80 00 | > INITRD IMG' FM
ADDRESS CMS 'pipe < ' zpxeparm ' | fblock 80 SPACE | > ' zpxeparm
return /* DownloadBinaries */
/* Procedure PunchFiles
Punch the kernel, initial RAMdisk, and PARM file.
Then IPL to start the install process.
*/
PunchFiles:
'CP SPOOL PUNCH *'
'CP CLOSE READER'
'CP PURGE READER ALL' /* clear reader contents */
ADDRESS CMS 'punch kernel img' FM '( noheader' /* punch kernel */
ADDRESS CMS 'punch zpxe parm' FM '( noheader' /* punch PARM file */
ADDRESS CMS 'punch initrd img' FM '( noheader' /* punch initrd */
ADDRESS CMS 'release' FM '(detach' /* release and detach the VDISK */
ADDRESS CMS 'exec vmlink tcpmaint 592 <detach>' /* and this disk */
'CP CHANGE READER ALL KEEP NOHOLD' /* keep files in reader */
'CP IPL 00C CLEAR' /* IPL the reader */
return /* PunchFiles */
/* Procedure ParseSystemRecord
Open system record file to look for local boot flag.
Return 0 if local flag found (guest will IPL default DASD).
Return 1 otherwise (guest will download kernel/initrd and install).
*/
ParseSystemRecord:
inputline = linein(profiledetail) /* get first line */
parse var inputline systemaction .
/* Close the file to reset the read pointer to the beginning. Yes I
know that calling lineout to close a file seems weird, but it's
how Rexx/Regina works. */
call lineout profiledetail
if systemaction = 'local' then
return 0
else
return 1
/* End ParseSystemRecord */