SHA256
1
0
forked from pool/s390-tools

Accepting request 459343 from openSUSE:Factory:zSystems

New package per "Factory first" policy. Please list me as bug owner and maintainer, if possible.

OBS-URL: https://build.opensuse.org/request/show/459343
OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=1
This commit is contained in:
Marcus Meissner 2017-02-21 11:14:26 +00:00 committed by Git OBS Bridge
commit 9b729e2acc
85 changed files with 21686 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

View File

@ -0,0 +1,14 @@
--- s390-tools-1.34.0/etc/udev/rules.d/59-dasd.rules 2016-04-22 13:37:54.000000000 -0400
+++ s390-tools-1.34.0/etc/udev/rules.d/59-dasd.rules 2016-04-22 13:38:15.000000000 -0400
@@ -33,11 +33,3 @@
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 deadline
-SUBSYSTEM!="block", GOTO="sched_end"
-
-ACTION!="add", GOTO="sched_end"
-KERNEL=="dasd*[!0-9]", WAIT_FOR="queue/scheduler", ATTR{queue/scheduler}="deadline"
-
-LABEL="sched_end"

13
59-graf.rules 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 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

183
appldata Normal file
View File

@ -0,0 +1,183 @@
#!/bin/sh
# Copyright (c) 2003 SUSE LINUX AG Nuernberg, Germany.
#
# Submit feedback to http://www.suse.de/feedback/
#
# /etc/init.d/appldata
#
# and symbolic its link
#
# /use/sbin/rcappldata
#
# System startup script for "Linux - z/VM Monitor Stream".
#
### BEGIN INIT INFO
# Provides: appldata
# Required-Start: $network $remote_fs
# Required-Stop: $null
# Default-Start: 3 5
# Default-Stop: 0 1 6
# Short-Description: Linux - z/VM Monitor Stream
# Description: Start the Linux - z/VM Monitor Stream
### END INIT INFO
#
# Local settings
LOCKFILE=/var/lock/appldata
CONFIGFILE=/etc/sysconfig/appldata
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_failed <num> set local and overall rc status to <num><num>
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
. /etc/rc.status
# First reset status of this service
rc_reset
# APPLDATA support in kernel?
if [ ! -e /proc/sys/appldata/interval ]; then
echo "No kernel support for \"Linux - z/VM Monitor Stream\"!"
exit 1
fi
# 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\" ..."
if [ -e $LOCKFILE ]; then
echo -n "(already running)"
rc_status -v
rc_exit
fi
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
rc_failed 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
rc_failed 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
rc_failed 1
else
echo 1 > /proc/sys/appldata/net_sum
fi
fi
fi
echo -n "(timer)"
echo 1 > /proc/sys/appldata/timer
touch $LOCKFILE
rc_status -v
}
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
rc_status -v
}
restart() {
stop
start
}
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
;;
restart|reload)
restart
;;
*)
echo "Usage: appldata {start|stop|status|restart|reload}"
RETVAL=1
esac
exit $RETVAL

56
boot.cpi Normal file
View File

@ -0,0 +1,56 @@
#!/bin/sh
#
# Copyright (c) 2001-2002 SuSE Linux AG, Nuernberg, Germany.
# Copyright (c) 2008 SuSE LINUX Products GmbH, Nuernberg, Germany.
# All rights reserved.
#
# /etc/init.d/boot.cpi
#
### BEGIN INIT INFO
# Provides: boot.cpi
# Required-Start: boot.rootfsck
# Required-Stop: $null
# Should-Start:
# X-Start-Before:
# Default-Start: B S
# Default-Stop:
# Description: Set Control Program Identification data
# Short-Description: Set Control Program Identification data
### END INIT INFO
. /etc/rc.status
. /etc/sysconfig/cpi
rc_reset
case "$1" in
start|restart|reload)
if test "$CPI_SET" == "yes"; then
if test ! -e /sys/firmware/cpi; then
echo -n "sclp_cpi interface not found"
rc_status -s
rc_exit
fi
echo "$CPI_SYSTEM_NAME" >/sys/firmware/cpi/system_name
echo "$CPI_SYSPLEX_NAME" >/sys/firmware/cpi/sysplex_name
echo "LINUX " >/sys/firmware/cpi/system_type
awk "BEGIN { split(\"`uname -r`\",x,\".\"); printf(\"0x0000000000%02x%02x%02x\", x[1],x[2],x[3]) }" >/sys/firmware/cpi/system_level
echo 1 >/sys/firmware/cpi/set 2>/dev/null
rc_status -v -r
else
rc_status -u
fi
;;
stop)
rc_status -s
;;
status)
rc_status -s
;;
*)
echo "Usage: $0 {start|stop|status|restart|reload}"
exit 1
;;
esac
rc_exit

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

67
cputype Normal file
View File

@ -0,0 +1,67 @@
#!/bin/sh
#
# cputype
#
# Copyright (c) 2014-2016 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 | /usr/bin/cut -f2- -d: | /usr/bin/tr -d ' ' | /usr/bin/tr ',' ';' )
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
eval ${args}
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)" ;;
*) 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.

317
ctc_configure Normal file
View File

@ -0,0 +1,317 @@
#! /bin/sh
#
# ctc_configure
#
# Configures a CTC device
#
# 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:
# 1 sysfs not mounted
# 2 Invalid status for <online>
# 3 No device found for read-channel
# 4 No device found for write-channel
# 5 Invalid device type
# 6 Device type mismatch
# 7 Could not load module
# 8 CCW devices grouped different devices
# 9 Could not group devices
# 10 Could not set device online
# 11 Could not set device offline
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATUM=$(date)
add_channel_for_cio() {
echo "$* # $DATUM" >> /boot/zipl/active_devices.txt
}
remove_channel_for_cio() {
[ -w /boot/zipl/active_devices.txt ] && sed -i -e "/^$1/d" /boot/zipl/active_devices.txt
}
mesg () {
echo "$@"
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
# 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
if [ $# -lt 3 ] ; then
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 uses that number"
echo " y is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the 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 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 operating systems."
exit 1
fi
CTC_READ_CHAN=$1
CTC_WRITE_CHAN=$2
ONLINE=$3
CTC_MODE=$4
[ -z "$CTC_MODE" ] && CTC_MODE=0
if [ -z "$ONLINE" ] || [ "$ONLINE" -ne "1" -a "$ONLINE" -ne "0" ]; then
mesg "Invalid device status $ONLINE"
exit 2
fi
_ccw_dir=${SYSFS}/bus/ccw/devices
debug_mesg "Configuring CTC/LCS device ${CTC_READ_CHAN}/${CTC_WRITE_CHAN}"
if test ! -d "$_ccw_dir/$CTC_READ_CHAN" ; then
mesg "device $_ccw_dir/$CTC_READ_CHAN does not exist"
exit 3
fi
if test ! -d "$_ccw_dir/$CTC_WRITE_CHAN" ; then
mesg "device $_ccw_dir/$CTC_WRITE_CHAN does not exist"
exit 4
fi
CCW_CHAN_GROUP=
for ccw in $_ccw_dir/$CTC_READ_CHAN $_ccw_dir/$CTC_WRITE_CHAN; do
read _cu_type < $ccw/cutype
read _dev_type < $ccw/devtype
case "$_cu_type" in
3088/01)
# P/390 network adapter
CCW_CHAN_NAME="cu3088"
CCW_CHAN_GROUP="lcs"
;;
3088/08)
# Channel To Channel
CCW_CHAN_NAME="cu3088"
CCW_CHAN_GROUP="ctcm"
;;
3088/1e)
# FICON adapter
CCW_CHAN_NAME="cu3088"
CCW_CHAN_GROUP="ctcm"
;;
3088/1f)
# ESCON adapter (I.e. hardware CTC device)
CCW_CHAN_NAME="cu3088"
CCW_CHAN_GROUP="ctcm"
;;
3088/60)
# Lan Channel Station
CCW_CHAN_NAME="cu3088"
CCW_CHAN_GROUP="lcs"
;;
*)
CCW_CHAN_NAME=
;;
esac
if [ -z "$CCW_CHAN_NAME" ]; then
mesg "Not a valid CTC device (cu $_cutype, dev $_devtype)"
exit 5
fi
[ -z "$tmp_chan" ] && tmp_chan=$CCW_CHAN_GROUP
done
if [ "$tmp_chan" != "$CCW_CHAN_GROUP" ] ; then
mesg "CTC type mismatch (read: $tmp_chan, write: $CCW_CHAN_GROUP)"
exit 6
fi
_ccw_groupdir=${SYSFS}/bus/ccwgroup
# Check for modules
if test ! -d "${_ccw_groupdir}/drivers/${CCW_CHAN_GROUP}" ; then
/sbin/modprobe $CCW_CHAN_GROUP
# Re-check whether module loading has succeeded
if test ! -d "${_ccw_groupdir}/drivers/${CCW_CHAN_GROUP}"; then
mesg "Could not load module ${CCW_CHAN_GROUP}"
exit 7
fi
fi
# Check for grouping
_ccw_status_dir=
if [ -e ${_ccw_dir}/${CTC_READ_CHAN}/group_device ] ; then
_ccw_status_dir=$(cd -P ${_ccw_dir}/${CTC_READ_CHAN}/group_device; echo $PWD)
fi
if [ -e ${_ccw_dir}/${CTC_WRITE_CHAN}/group_device ] ; then
_tmp_status_dir=$(cd -P ${_ccw_dir}/${CTC_READ_CHAN}/group_device; echo $PWD)
if [ "$_ccw_status_dir" ] && [ "$_ccw_status_dir" != "$_tmp_status_dir" ] ; then
mesg "CCW devices grouped to different devices"
exit 8
fi
_ccw_status_dir=$_tmp_status_dir
fi
#
# Addresses are free (but may be bound to the wrong driver)
#
_ccw_drivers=${SYSFS}/bus/ccw/drivers
for i in ${CTC_READ_CHAN} ${CTC_WRITE_CHAN}
do
if [ "$CCW_CHAN_GROUP" = "lcs" ]
then
if [ -e "${_ccw_drivers}/ctcm/${i}" ] ; then
echo $i > ${_ccw_drivers}/ctcm/unbind
fi
if [ ! -e "${_ccw_drivers}/lcs/${i}" ] ; then
echo $i > ${_ccw_drivers}/ctcm/bind
fi
else
if [ -e "${_ccw_drivers}/lcs/${i}" ] ; then
echo $i > ${_ccw_drivers}/lcs/unbind
fi
if [ ! -e "${_ccw_drivers}/ctcm/${i}" ] ; then
echo $i > ${_ccw_drivers}/ctcm/bind
fi
fi
done
debug_mesg "Group is ${_ccw_groupdir}/drivers/${CCW_CHAN_GROUP}/group"
if [ -z "$_ccw_status_dir" ] ; then
echo "$CTC_READ_CHAN,$CTC_WRITE_CHAN" > ${_ccw_groupdir}/drivers/${CCW_CHAN_GROUP}/group
if [ -e ${_ccw_dir}/${CTC_READ_CHAN}/group_device ] ; then
_ccw_status_dir=$(cd -P ${_ccw_dir}/${CTC_READ_CHAN}/group_device; echo $PWD)
fi
fi
if [ -z "$_ccw_status_dir" -o ! -e "$_ccw_status_dir" ] ; then
mesg "Could not group $CCW_CHAN_GROUP devices $CTC_READ_CHAN/$CTC_WRITE_CHAN"
exit 9
fi
CCW_CHAN_ID=${_ccw_status_dir##*/}
read _ccw_dev_status < $_ccw_status_dir/online
if [ "$ONLINE" -eq 1 ]; then
# Check whether we need to do something
if [ "$_ccw_dev_status" -eq 0 ]; then
if [ "$CTC_MODE" -gt 0 -a "$CCW_CHAN_GROUP" != "lcs" ]; then
echo $CTC_MODE > $_ccw_status_dir/protocol
fi
# Set the device online
debug_mesg "Setting device online"
echo "1" > $_ccw_status_dir/online
# Re-read device status
read _ccw_dev_status < $_ccw_status_dir/online
if [ "$_ccw_dev_status" -eq 0 ]; then
mesg "Could not set device ${CCW_CHAN_ID} online"
exit 10
fi
else
debug_mesg "Device ${CCW_CHAN_ID} is already online"
fi
else
if [ "$_ccw_dev_status" -eq 1 ]; then
# Set the device offline
debug_mesg "Setting device offline"
echo "$ONLINE" > $_ccw_status_dir/online
# Re-read to check whether we have succeeded
_ccw_dev_status=$(cat $_ccw_status_dir/online)
if [ "$_ccw_dev_status" -ne "$ONLINE" ]; then
mesg "Could not set device ${CCW_CHAN_ID} offline"
exit 11
fi
else
debug_mesg "Device ${CCW_CHAN_ID} is already offline"
fi
# Always reset CTC Protocol
if [ "$CCW_CHAN_GROUP" != "lcs" ]; then
echo 0 > $_ccw_status_dir/protocol
fi
fi
RULES_DIR=/etc/udev/rules.d
RULES_FILE=51-${CCW_CHAN_GROUP}-${CCW_CHAN_ID}.rules
if [ -d "$RULES_DIR" ]; then
if [ -f ${RULES_DIR}/${RULES_FILE} ]; then
rm -f ${RULES_DIR}/${RULES_FILE}
fi
remove_channel_for_cio "$CTC_READ_CHAN"
remove_channel_for_cio "$CTC_WRITE_CHAN"
if [ "$ONLINE" -eq "1" ]; then
add_channel_for_cio "$CTC_READ_CHAN,$CTC_WRITE_CHAN"
# Write a new udev rules file
cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configure ${CCW_CHAN_GROUP} device at ${CTC_READ_CHAN}/${CTC_WRITE_CHAN} (Protocol ${CTC_MODE})
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", RUN+="/sbin/modprobe --quiet $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", DRIVER!="?*", GOTO="ctc-${CTC_READ_CHAN}-no-unbind"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", DRIVER=="ctcm", GOTO="ctc-${CTC_READ_CHAN}-no-unbind"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", ATTR{driver/unbind}="$CTC_READ_CHAN"
LABEL="ctc-${CTC_READ_CHAN}-no-unbind"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", DRIVER!="?*", ATTR{[drivers/ccw:ctcm]bind}="$CTC_READ_CHAN"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", DRIVER!="?*", GOTO="ctc-${CTC_WRITE_CHAN}-no-unbind"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", DRIVER=="ctcm", GOTO="ctc-${CTC_WRITE_CHAN}-no-unbind"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", ATTR{driver/unbind}="$CTC_WRITE_CHAN"
LABEL="ctc-${CTC_WRITE_CHAN}-no-unbind"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", DRIVER!="?*", ATTR{[drivers/ccw:ctcm]bind}="$CTC_WRITE_CHAN"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", RUN+="/sbin/modprobe --quiet $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_CHAN_GROUP", IMPORT{program}="collect $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$CTC_READ_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$CTC_WRITE_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
ACTION=="remove", SUBSYSTEM=="drivers", KERNEL=="$CCW_CHAN_GROUP", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $CTC_READ_CHAN $CTC_WRITE_CHAN $CCW_CHAN_GROUP"
TEST=="[ccwgroup/${CCW_CHAN_ID}]", GOTO="ctc-${CCW_CHAN_ID}-end"
ACTION=="add", SUBSYSTEM=="ccw", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[drivers/ccwgroup:$CCW_CHAN_GROUP]group}="$CTC_READ_CHAN,$CTC_WRITE_CHAN"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_CHAN_GROUP", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{group}="$CTC_READ_CHAN,$CTC_WRITE_CHAN"
LABEL="ctc-${CCW_CHAN_ID}-end"
EOF
if [ "$CTC_MODE" -gt 0 ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{protocol}="$CTC_MODE"
EOF
fi
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{online}="1"
EOF
fi
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.

409
dasd_configure Normal file
View File

@ -0,0 +1,409 @@
#! /bin/sh
#
# dasd_configure
# $Id: dasd_configure,v 1.10 2004/11/26 15:50:48 hare Exp $
#
# Copyright (c) 2001-2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
# Configures or deconfigures a DASD device
#
# Usage:
# dasd_configure [-f -t <dasd_type> ] <ccwid> <online> [use_diag]
#
# -f force creation of udev rules, do not check values in /sys.
# -t DASD type. Must be provided if -f is used.
# ccwid = 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
# 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:
# 1 If the "Usage:" line is displayed, not enough parameters specified.
# 1 sysfs not mounted (if the "Usage:" line is not displayed).
# 2 Invalid status for <online>
# 3 No device found for <ccwid>
# 4 Could not change state of the device
# 5 Device is not a DASD
# 6 Could not load module
# 7 Failed to activate DASD
# 8 DASD not formatted
# 9 Only dasd-fba or dasd-eckd is supported.
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
exitcode=0
DASD_FORCE=0
DASD_TYPE="unknown"
DATUM=$(date)
add_channel_for_cio() {
echo "$* # $DATUM" >> /boot/zipl/active_devices.txt
}
remove_channel_for_cio() {
[ -w /boot/zipl/active_devices.txt ] && sed -i -e "/^$1/d" /boot/zipl/active_devices.txt
}
mesg () {
echo "$@"
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
if [ $# -lt 2 ] ; then
echo "Usage: $0 [options] <ccwid> <online> [use_diag]"
echo
echo " -f force creation of udev rules, do not check values in /sys."
echo " -t DASD type. Must be provided if -f is used."
echo " ccwid = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the device, in 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"
exit 1
fi
while [ $# -gt 0 ] ; do
case "$1" in
-f) # force creation of udev rules, do not check values in /sys
DASD_FORCE=1
;;
-t*) # drive type. Must be provided if -f is used.
if [ "$1" = "-t" ] ; then
if [ "$2" = "dasd-eckd" -o "$2" = "dasd-fba" ]; then
DASD_TYPE=$2
shift
else
debug_mesg "Only dasd-eckd or dasd-fba are supported."
exit 9
fi
fi
;;
*)
break;
;;
esac
shift
done
if [ $DASD_FORCE -eq 0 ]; then
# 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
else
CCW_CHAN_NAME=$DASD_TYPE
case $DASD_TYPE in
*eckd)
DISCIPLINE=ECKD
;;
*fba)
DISCIPLINE=FBA
;;
*)
mesg "Only dasd-eckd or dasd-fba are supported."
exit 9
;;
esac
fi # First instance of if [ $DASD_FORCE -eq 0 ]
CCW_CHAN_ID=$1
ONLINE=$2
USE_DIAG=$3
[ -z "$USE_DIAG" ] && USE_DIAG=0
if [ -z "$ONLINE" ] || [ "$ONLINE" -ne "1" -a "$ONLINE" -ne "0" ]; then
mesg "Invalid device status $ONLINE"
mesg "It must be a zero or a one."
exit 2
fi
if [ $DASD_FORCE -eq 0 ]; then
_ccw_dir=${SYSFS}/bus/ccw/devices
debug_mesg "Configuring device ${CCW_CHAN_ID}"
_ccw_status_dir="$_ccw_dir/$CCW_CHAN_ID"
if test ! -d "$_ccw_status_dir" ; then
if test "$ONLINE" -eq 1 ; then
mesg "No device ${CCW_CHAN_ID}"
exit 3
fi
_ccw_dev_status=0
else
read _cu_type < $_ccw_status_dir/cutype
read _dev_type < $_ccw_status_dir/devtype
case "$_cu_type" in
3990/*|2105/*|2107/*|1750/*|9343/*)
CCW_CHAN_NAME="dasd-eckd"
MODULE=dasd_eckd_mod
DISCIPLINE=ECKD
;;
6310/*)
CCW_CHAN_NAME="dasd-fba"
MODULE=dasd_fba_mod
DISCIPLINE=FBA
;;
3880/*)
case "$_dev_type" in
3390/*)
CCW_CHAN_NAME="dasd-eckd"
MODULE=dasd_eckd_mod
DISCIPLINE=ECKD
;;
3370/*)
CCW_CHAN_NAME="dasd-fba"
MODULE=dasd_fba_mod
DISCIPLINE=FBA
;;
*)
CCW_CHAN_NAME=
;;
esac
;;
*)
CCW_CHAN_NAME=
;;
esac
if [ -z "$CCW_CHAN_NAME" ]; then
mesg "Not a DASD device (cu $_cutype, dev $_devtype)"
exit 5
fi
# Check for modules
if test ! -d "${SYSFS}/bus/ccw/drivers/${CCW_CHAN_NAME}" ; then
/sbin/modprobe $MODULE
# Re-check whether module loading has succeeded
if test ! -d "${SYSFS}/bus/ccw/drivers/${CCW_CHAN_NAME}"; then
mesg "Could not load module ${MODULE}"
exit 6
fi
fi
read _ccw_dev_status < $_ccw_status_dir/online
fi # if test ! -d "$_ccw_status_dir"
#
# We check whether we are running under z/VM by looking for the string
# "Control Program: z/VM" in /proc/sysinfo
#
/bin/grep "Control Program: z/VM" /proc/sysinfo 2>&1 > /dev/null
if [ -x /sbin/vmcp -a $? -eq 0 ]; then
# Unconditionally load the vmcp module, loader might be broken
[ -x /sbin/modprobe ] && /sbin/modprobe -q vmcp
# Wait until udev is settled
[ -x /sbin/udevadm ] && /sbin/udevadm settle --timeout=30
# Check read-only status of virtual DASDs from z/VM
if /sbin/vmcp q v dasd > /dasd_attr.lst 2> /dev/null; then
while read x dev type label attr1 attr2 rest; do
dev=`echo $dev|tr A-F a-f`
if test "$type" = "ON"; then
attr="$attr2"
else
attr="$attr1"
fi
if [ "$CCW_CHAN_ID" = "0.0.$dev" ]; then
if test "$attr" = "R/O"; then
_ccw_use_readonly="1"
fi
fi
done < /dasd_attr.lst
fi
rm -f /dasd_attr.lst
fi # if [ -x /sbin/vmcp -a $? -eq 0 ]
if [ "$ONLINE" -eq 1 ]; then
# Check whether we need to do something
read _ccw_use_diag < $_ccw_status_dir/use_diag
if [ "$_ccw_use_diag" -ne "$USE_DIAG" ] &&
[ "$_ccw_dev_status" -eq 1 ] ; then
# We need to change the DIAG access mode
# so we have to set the device offline first
debug_mesg "Setting device offline for DIAG access"
echo "0" > $_ccw_status_dir/online
# Re-read device status
read _ccw_dev_status < $_ccw_status_dir/online
if [ "$_ccw_dev_status" -ne 0 ]; then
mesg "Could not set the device offline for DIAG access"
exit 4
fi
fi
if [ "$_ccw_dev_status" -eq 0 ]; then
# Set readonly access if detected
if [ "$_ccw_use_readonly" ]; then
debug_mesg "Setting device read-only"
echo 1 > $_ccw_status_dir/readonly
fi
if [ "$USE_DIAG" -eq 1 ]; then
# Load the diag module if possible
[ -x /sbin/modprobe ] && /sbin/modprobe -q dasd_diag_mod
_has_dasd_diag=$(/bin/sed -n '/^dasd_diag_mod/p' /proc/modules)
if [ "$_has_dasd_diag" ]; then
# DIAG mode is special:
# We can only be sure if DIAG is available
# _after_ we have activated the device
debug_mesg "Activating DIAG access mode"
echo "$USE_DIAG" > $_ccw_status_dir/use_diag
read _ccw_use_diag < $_ccw_status_dir/use_diag
# Set the device online
debug_mesg "Setting device online"
echo "1" > $_ccw_status_dir/online 2>/dev/null
# Re-read device status
read _ccw_dev_status < $_ccw_status_dir/online
if [ "$_ccw_dev_status" -eq 0 ]; then
mesg "Could not activate DIAG access mode for device ${CCW_CHAN_ID}"
USE_DIAG=0
echo "$USE_DIAG" > $_ccw_status_dir/use_diag
# Set the device online
debug_mesg "Setting device online"
echo "1" > $_ccw_status_dir/online
else
MODULE=dasd_diag_mod
fi
else
debug_mesg "DIAG mode not available"
USE_DIAG=0
# Set the device online
debug_mesg "Setting device online"
echo "1" > $_ccw_status_dir/online
fi # if [ "$_has_dasd_diag" ];
else
if [ "$_ccw_use_diag" -eq 1 ] ; then
debug_mesg "Deactivating DIAG access mode"
echo "0" > $_ccw_status_dir/use_diag
read _ccw_use_diag < $_ccw_status_dir/use_diag
fi
# Set the device online
debug_mesg "Setting device online"
echo "1" > $_ccw_status_dir/online
fi # if [ "$USE_DIAG" -eq 1 ]
# Re-read device status
read _ccw_dev_status < $_ccw_status_dir/online
if [ "$_ccw_dev_status" -eq 0 ]; then
mesg "Could not set device ${CCW_CHAN_ID} online"
exit 4
fi
# Wait for the device to come online
read _dasd_state < $_ccw_status_dir/status
i=0
while [ "$_dasd_state" != "online" ] ; do
if [ "$_dasd_state" = "unformatted" ] ; then
mesg "Device ${CCW_CHAN_ID} is unformatted"
exitcode=8
break
fi
[ $i -gt 30 ] && break
i=$(expr $i + 1)
sleep .1
read _dasd_state < $_ccw_status_dir/status
done
else
debug_mesg "Device ${CCW_CHAN_ID} is already online"
fi # if [ "$_ccw_dev_status" -eq 0 ]
read _dasd_state < $_ccw_status_dir/status
if [ "$_dasd_state" != "online" ] && [ "$_dasd_state" != "unformatted" ] ; then
mesg "Failed to activate device ${CCW_CHAN_ID}, device in state $_dasd_state"
exit 7
fi
else
if [ "$_ccw_dev_status" -eq 1 ]; then
# Set the device offline
debug_mesg "Setting device offline"
echo "$ONLINE" > $_ccw_status_dir/online
# Re-read to check whether we have succeeded
_ccw_dev_status=$(cat $_ccw_status_dir/online)
if [ "$?" -ne 0 -o "$_ccw_dev_status" -ne "$ONLINE" ]; then
mesg "Could not set device ${CCW_CHAN_ID} offline"
exit 4
fi
else
debug_mesg "Device ${CCW_CHAN_ID} is already offline"
fi
if [ -d "$_ccw_status_dir" ] ; then
# Always disabling DIAG access
echo "0" > $_ccw_status_dir/use_diag
fi
# Set readonly access if detected
if [ "$_ccw_use_readonly" ]; then
debug_mesg "Setting device read-only"
echo 1 > $_ccw_status_dir/readonly
fi
fi # if [ "$ONLINE" -eq 1 ]
# Wait until udev is settled
[ -x /sbin/udevadm ] && /sbin/udevadm settle --timeout=30
fi # Second instance of if [ $DASD_FORCE -eq 0 ]
if [ $DEBUG = "no" ]; then
RULES_DIR=/etc/udev/rules.d
else
RULES_DIR=.
fi
RULES_FILE=51-dasd-${CCW_CHAN_ID}.rules
if [ -d "$RULES_DIR" ]; then
if [ -f ${RULES_DIR}/${RULES_FILE} ]; then
rm -f ${RULES_DIR}/${RULES_FILE}
fi
remove_channel_for_cio "${CCW_CHAN_ID}"
if [ "$ONLINE" -eq "1" ]; then
add_channel_for_cio "${CCW_CHAN_ID}"
# Write a new hwcfg file
cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configure DASD device at ${CCW_CHAN_ID} (${DISCIPLINE} mode)
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="${CCW_CHAN_ID}", IMPORT{program}="collect ${CCW_CHAN_ID} %k ${CCW_CHAN_ID} ${CCW_CHAN_NAME}"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="${CCW_CHAN_NAME}", IMPORT{program}="collect ${CCW_CHAN_ID} %k ${CCW_CHAN_ID} ${CCW_CHAN_NAME}"
EOF
if [ "$USE_DIAG" -eq 1 ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", ENV{COLLECT_${CCW_CHAN_ID}}=="0", ATTR{[ccw/$CCW_CHAN_ID]use_diag}="1"
EOF
fi
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", ENV{COLLECT_${CCW_CHAN_ID}}=="0", ATTR{[ccw/$CCW_CHAN_ID]online}="1"
EOF
fi
fi
exit $exitcode

152
dasd_configure.8 Normal file
View File

@ -0,0 +1,152 @@
.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 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
.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
.I /etc/udev/rules.d/51-dasd-<ccwid>.rules
.RS
This file provides the udev rules necessary to activate a specific DASD volume.
.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 It must be a zero or a one.
.RS
A value other than 0 or 1 was specified for the second parameter, online. Return code 2 is set.
.RE
.IP
.B No device ${CCW_CHAN_ID}
.RS
A non-existent <ccwid> was specified for the DASD volume. Remember the x.y.ssss format is necessary. Return code 3 is set.
.RE
.IP
.B Could not set the device offline for DIAG access
.RS
You specified that the DIAG driver be used for this device. However, the device was already online without DIAG mode set, and something prevented it from being taken offline. (The use_diag value can only be modified when the disk is offline to the system.) Return code 4 is set.
.RE
.IP
.B Could not set device ${CCW_CHAN_ID} online
.RS
The attempt to bring the DASD volume online failed. Try "dmesg" to see if there is any indication why. Return code 4 is set.
.RE
.IP
.B Could not set device ${CCW_CHAN_ID} offline
.RS
The attempt to take the DASD volume offline failed. Try "dmesg" to see if there is any indication why. Return code 4 is set.
.RE
.IP
.B Not a DASD device (cu $_cutype, dev $_devtype)
.RS
The ccwid you specified does not refer to a DASD volume. Return code 5 is set.
.RE
.IP
.B Could not load module ${MODULE}
.RS
The dasd_eckd_mod.ko or dasd_fba_mod.ko module failed to load. Try "dmesg" to see if there is any indication why. Return code 6 is set.
.RE
.IP
.B Failed to activate device ${CCW_CHAN_ID}, device in state $_dasd_state
.RS
The attempt to bring the DASD volume online failed. The volume was left in the state described (which will not be online or offline.) Return code 7 is set.
.RE
.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. The udev rules are not created. After the disk has been formatted, re-run dasd_configure to take the volume offline, and then again to bring it online. Return code 8 is set.
.RE
.IP
.B Only dasd-eckd or dasd-fba are supported.
.RS
Either an invalid -t value was specified, or -f was specified without -t. Return code 9 is set.
.RE
If environment variable DEBUG is set to "yes," the following messages may be issued on stdout:
.IP
.B Configuring device ${CCW_CHAN_ID}
.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 Setting device offline for DIAG access
.RS
Just a little bit of verbosity.
.RE
.IP
.B Setting device read-only
.RS
Just a little bit of verbosity.
.RE
.IP
.B Activating DIAG access mode
.RS
Just a little bit of verbosity.
.RE
.IP
.B DIAG mode not available
.RS
You specified that the DIAG driver should be used for this DASD volume. The script tried to honor this, but was not able to do so. Non-DIAG mode was used instead.
.RE
.IP
.B Deactivating DIAG access mode
.RS
You specified that the DIAG driver NOT be used for this DASD volume, but the use_diag flag was already set for it.
.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 DASD volume 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 DASD volume offline when it was already offline.
.RE
.SH BUGS
Gotta be some, I'm sure. If you find one, please open a bug report.

137
dasd_reload Normal file
View File

@ -0,0 +1,137 @@
#!/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
if [ -d /etc/udev/rules.d ]; then
cd /etc/udev/rules.d
#
# Re-activating "normal" DASD and HyperPAV base devices
#
for dasd in $dasd_base; do
file="51-dasd-${dasd}.rules"
if [ -f "$file" ] ; then
echo Activating $dasd
if grep -q use_diag $file ; then
DASD_USE_DIAG=1
else
DASD_USE_DIAG=0
fi
/sbin/dasd_configure $dasd 1 $DASD_USE_DIAG
fi
done
#
# Re-activating HyperPAV alias devices
#
for dasd in $dasd_alias; do
file="51-dasd-${dasd}.rules"
if [ -f "$file" ] ; then
echo Activating $dasd
if grep -q use_diag $file ; then
DASD_USE_DIAG=1
else
DASD_USE_DIAG=0
fi
/sbin/dasd_configure $dasd 1 $DASD_USE_DIAG
fi
done
fi
exit ${EXITRC}

View File

@ -0,0 +1,71 @@
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 | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/dasdfmt/dasdfmt.c b/dasdfmt/dasdfmt.c
index e1877ac..f03cbad 100644
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -270,7 +270,7 @@ static void init_info(dasdfmt_info_t *info)
static void check_disk(dasdfmt_info_t *info)
{
dasd_information_t dasd_info;
- int ro, errno_save;
+ int ro, errno_save, i = 0;
if (ioctl(filedes, BLKROGET, &ro) != 0) {
errno_save = errno;
@@ -283,7 +283,7 @@ static void check_disk(dasdfmt_info_t *info)
if (ro) {
ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n");
}
-
+retry:
if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
errno_save = errno;
close(filedes);
@@ -294,8 +294,23 @@ static void check_disk(dasdfmt_info_t *info)
}
if (!info->force)
- if (dasd_info.open_count > 1)
+ /*
+ * udev strikes again.
+ * Modern udev will issue a 'change' event whenever
+ * a device opened with O_RDWR is closed again.
+ * On the ground that program _might_ have changed
+ * the partition table.
+ * And confusing the hell out ouf anyone else.
+ * Bah.
+ */
+ if (dasd_info.open_count > 1) {
+ if (i < 5) {
+ ++i;
+ sleep(1);
+ goto retry;
+ }
ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n");
+ }
info->usage_count = dasd_info.open_count;
info->devno = dasd_info.devno;
--
1.8.4.5

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

158
detach_disks.sh Normal file
View File

@ -0,0 +1,158 @@
#!/bin/sh
COOKIE=$(mcookie)
DASDFILE=/tmp/dasd.list.${COOKIE}
DETFILE=/tmp/detach.disks.${COOKIE}
KEEPFILE=/tmp/keep.disks.${COOKIE}
NICFILE=/tmp/nic.list.${COOKIE}
FAILFILE=/tmp/error.${COOKIE}
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}

258
hsnc Normal file
View File

@ -0,0 +1,258 @@
#! /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
#
### BEGIN INIT INFO
# Provides: hsnc
# Required-Start: $network $remote_fs
# Required-Stop: $null
# Default-Start: 3 5
# Default-Stop: 0 1 6
# Short-Description: HiperSockets Network Concentrator
# Description: Start the qeth HiperSockets Network Concentrator
### END INIT INFO
#
#
#
#
#
#
# /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
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_failed <num> set local and overall rc status to <num><num>
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
. /etc/rc.status
# First reset status of this service
rc_reset
# 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:
return 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 [ -e /sys/devices/qeth ]; then
echo -n "Starting $service "
else
echo -n "- cannot start $service, no /sys/devices/qeth "
rc_failed 1
fi
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
fi
fi
# Remember status and be verbose
rc_status -v
;;
stop)
echo -n "Shutting down $service "
# kill ip_watcher, start_hsnc, which started it needs cleans up
# then:
killproc -TERM $IP_WATCHER_BIN
rc_failed $?
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
# Remember status and be verbose
rc_status -v
;;
try-restart)
## Stop the service and if this succeeds (i.e. the
## service was running before), start it again.
## Note: try-restart is not (yet) part of LSB (as of 0.7.5)
$0 status >/dev/null && $0 restart
# Remember status and be quiet
rc_status
;;
restart)
## Stop the service and regardless of whether it was
## running or not, start it again.
$0 stop
$0 start
# Remember status and be quiet
rc_status
;;
force-reload)
## start_hsnc.sh does not listen to signals
echo -n "Force-reload $service "
$0 stop && $0 start
rc_status
;;
reload)
## start_hsnc.sh does not listen to signals
echo -n "Reload $service: not supported"
## it does not support reload:
rc_failed 3
rc_status -v
;;
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
rc_status -v
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart}"
exit 1
;;
esac
rc_exit

133
iucv_configure 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

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.

217
killcdl 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.2
.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.

584
mkdump.pl Normal file
View File

@ -0,0 +1,584 @@
#!/usr/bin/perl
########################################################################
#
# mkdump.pl - Preparing disks for use as S/390 dump device
#
# Copyright (c) 2011 Tim Hardeck, SUSE LINUX Products GmbH
# bases 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.2";
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";
my $MNTPOINT = "/var/run/mkdump." . getppid();
# temporary DASD device configuration file for Zipl
my $MDPATH = "/tmp/mvdump.conf";
# zFCP dump dir, without a leading '/'
my $ZFCP_DUMP_DIR = "mydumps";
my $OPT_DEBUG = 0;
my $OPT_FORCE = 0;
my $OPT_VERBOSE = 0;
sub cleanup
{
# DASD
if (-e $MDPATH) {
system("rm -f $MDPATH");
}
# zFCP
if (-d $MNTPOINT) {
system("umount $MNTPOINT");
system("rmdir $MNTPOINT");
}
}
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 is_zfcp
{
# remove leading /dev/
my $device = substr(shift(), 5);
my $devpath = "/sys/block/$device/device";
unless (-r "$devpath/hba_id" or -r "$devpath/type") {
return(0);
}
my $devtype = read_file("$devpath/type");
# SCSI type '0' means disk
if ($devtype == 0) {
return(1);
} else {
return(0);
}
}
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 = "/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 {
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
system("mkdir -p $MNTPOINT");
if (get_partition_num($device) == 1 and system("mount -o ro ${device}1 $MNTPOINT 2>/dev/null") == 0) {
if ( -r "$MNTPOINT/bootmap" and -d "$MNTPOINT/$ZFCP_DUMP_DIR") {
$dump_device = 1;
$output .= "\tdumpdevice";
}
system("umount $MNTPOINT");
}
system("rmdir $MNTPOINT");
}
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*
if ($file =~ /^dasd[a-z]+$/ or $file =~ /^sd[a-z]+$/) {
push(@devices, $file);
}
}
closedir(DIR);
for my $entry (@devices) {
# only allow disks, no partitions
my ($device) = $entry =~ /^([a-z]+)$/;
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);
}
if (is_zfcp($device)) {
push(@zfcp, $device);
}
}
}
return(\@dasd, \@zfcp);
}
sub prepare_dasd
{
my @devices = @_;
my $format_disks = "";
# check formatting
for my $device (@devices) {
# determine disk layout
my ($fmtstr) = `$DASDVIEW -x -f $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
my $md_path = "/tmp/mvdump.conf";
# don't create files in debug mode
unless ($OPT_DEBUG) {
open(my $file, ">", $md_path) or exit_with("Unable to access $md_path: $!.", 15);
for my $device (@devices) {
print{$file}("${device}1\n");
}
close($file);
}
print("Creating dump record.\n");
run_cmd("${ZIPL} -V -n -M $md_path");
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");
run_cmd("${ZIPL} -V -d ${device}1");
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);
}
if ( $device =~ /^\/dev\/[a-z]+$/ == 0) {
exit_with("The device parameter $device is inaccurate. Only whole disks are allowed.", 14);
}
if (grep(/$device/, (@$dasd_ref, @$zfcp_ref))) {
if (is_zfcp($device) and @ARGV > 1) {
exit_with("Multi-volume dumps aren't supported with zFCP.", 14);
}
push(@devices, $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
if (is_zfcp($devices[0])) {
setup_zfcpdump($devices[0]);
} else {
setup_dasddump(@devices);
}
print("Creating the dump device was successful.\n");
}
main();

452
qeth_configure Normal file
View File

@ -0,0 +1,452 @@
#! /bin/sh
#
# qeth_configure
#
# Configures a qeth device
#
# 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 force creation of udev rules, do not check values in /sys
# -t Valid cardtypes are: qeth, hsi, osn
# -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. Only needed if sharing a real OSA with z/OS.
# 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:
# 1 sysfs not mounted
# 2 Invalid status for <online>
# 3 No device found for read channel
# 4 No device found for write channel
# 5 No device found for data channel
# 6 Invalid device type
# 7 Could not load module
# 8 CCW devices grouped different devices
# 9 Could not group devices
# 10 Could not set device online
# 11 Could not set device offline
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
QETH_FORCE=0
mesg () {
echo "$@"
}
DATUM=$(date)
add_channel_for_cio() {
echo "$* # $DATUM" >> /boot/zipl/active_devices.txt
}
remove_channel_for_cio() {
[ -w /boot/zipl/active_devices.txt ] && sed -i -e "/^$1/d" /boot/zipl/active_devices.txt
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
while [ $# -gt 0 ] ; do
case "$1" in
-i)
# Configure IP takeover
QETH_IPA_TAKEOVER=1
;;
-f) # force creation of udev rules, do not check values in /sys
QETH_FORCE=1
;;
-l)
# Configure Layer2 support
QETH_LAYER2_SUPPORT=1
;;
-n*)
# QETH port number to use
if [ "$1" = "-n" ] ; then
QETH_PORTNO=$2
shift
else
QETH_PORTNO=${1#-n}
fi
;;
-o)
# General QETH options, separated by spaces
QETH_OPTIONS=$2
shift
;;
-p*)
# QETH Portname to use
if [ "$1" = "-p" ] ; then
QETH_PORTNAME=$2
shift
else
QETH_PORTNAME=${1#-p}
fi
;;
-t*) # Card type. Must be provided if -f is used.
if [ "$1" = "-t" ] ; then
if [ "$2" = "qeth" -o "$2" = "hsi" -o "$2" = "osn" ]; then
QETH_CARD=$2
shift
else
mesg "Only qeth, hsi and osn are supported."
exit 6
fi
fi
CCW_DRV="$QETH_CARD"
;;
*)
break;
;;
esac
shift
done
if [ $QETH_FORCE -eq 0 ]; then
# 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
fi
QETH_READ_CHAN=$1
QETH_WRITE_CHAN=$2
QETH_DATA_CHAN=$3
ONLINE=$4
if [ $# -lt 4 ] ; then
echo "Usage: $0 [options] <read chan> <write chan> <data chan> <online>"
echo " -i Configure IP takeover"
echo " -l Configure Layer2 support"
echo " -f force creation of udev rules, do not check values in /sys"
echo " -t Valid cardtypes are: qeth, hsi, osn"
echo " -o General QETH options, separated by spaces"
echo " -n QETH port number to use, 0 or 1. Only needed for real, not virtual devices."
echo " -p QETH Portname to use. Only needed if sharing a real OSA with z/OS."
echo " read/write/data chan = x.y.ssss where"
echo " x is always 0 until IBM creates something that uses that number"
echo " y is the logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the device, in hexidecimal, with leading zeros."
echo " online = 0 to take the device offline"
echo " 1 to bring the device online"
exit 1
fi
if [ -z "$ONLINE" ] || [ "$ONLINE" -ne "1" -a "$ONLINE" -ne "0" ]; then
mesg "Invalid device status $ONLINE"
exit 2
fi
if [ $QETH_FORCE -eq 0 ]; then
_ccw_dir=${SYSFS}/bus/ccw/devices
# Convert any hexidecimal numbers to lower case
QETH_READ_CHAN=$(echo ${QETH_READ_CHAN} | tr "[A-Z]" "[a-z]")
QETH_WRITE_CHAN=$(echo ${QETH_WRITE_CHAN} | tr "[A-Z]" "[a-z]")
QETH_DATA_CHAN=$(echo ${QETH_DATA_CHAN} | tr "[A-Z]" "[a-z]")
debug_mesg "Configuring QETH device ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_DATA_CHAN}"
if test ! -d "$_ccw_dir/$QETH_READ_CHAN" ; then
mesg "No device ${QETH_READ_CHAN}"
exit 3
fi
if test ! -d "$_ccw_dir/$QETH_WRITE_CHAN" ; then
mesg "No device ${QETH_WRITE_CHAN}"
exit 4
fi
if test ! -d "$_ccw_dir/$QETH_DATA_CHAN" ; then
mesg "No device ${QETH_DATA_CHAN}"
exit 5
fi
CCW_CHAN_GROUP=
for ccw in $_ccw_dir/$QETH_READ_CHAN $_ccw_dir/$QETH_WRITE_CHAN $_ccw_dir/$QETH_DATA_CHAN; do
read _cu_type < $ccw/cutype
read _dev_type < $ccw/devtype
case "$_cu_type" in
1731/01|1731/02)
# OSA/Express / Guest LAN
CCW_DRV="qeth"
QETH_CARD="qeth"
;;
1731/05)
# Hipersockets
CCW_DRV="qeth"
QETH_CARD="hsi"
;;
1731/06)
# OSA/N
CCW_DRV="qeth"
QETH_CARD="osn"
;;
*)
CCW_DRV=
;;
esac
if [ -z "$CCW_DRV" ]; then
mesg "Not a valid QETH device (cu $_cutype, dev $_devtype)"
exit 6
fi
done
fi # end QETH_FORCE
# Portname is only required for OSA/Express
if [ -n "$QETH_PORTNAME" -a "$QETH_CARD" != "qeth" ] ; then
debug_mesg "No portname required for $QETH_CARD adapters"
QETH_PORTNAME=
fi
if [ $QETH_FORCE -eq 0 ]; then
_ccw_groupdir=${SYSFS}/bus/ccwgroup
# Check for modules
if test ! -d "${_ccw_groupdir}/drivers/${CCW_DRV}" ; then
/sbin/modprobe $CCW_DRV
# Re-check whether module loading has succeeded
if test ! -d "${_ccw_groupdir}/drivers/${CCW_DRV}"; then
mesg "Could not load module ${CCW_DRV}"
exit 7
fi
fi
# Check for grouping
_ccwgroup_dir=
if [ -e ${_ccw_dir}/${QETH_READ_CHAN}/group_device ] ; then
_ccwgroup_dir=$(cd -P ${_ccw_dir}/${QETH_READ_CHAN}/group_device; echo $PWD)
fi
if [ -e ${_ccw_dir}/${QETH_WRITE_CHAN}/group_device ] ; then
_tmp_status_dir=$(cd -P ${_ccw_dir}/${QETH_READ_CHAN}/group_device; echo $PWD)
if [ "$_ccwgroup_dir" ] && [ "$_ccwgroup_dir" != "$_tmp_status_dir" ] ; then
mesg "CCW devices grouped to different devices"
exit 8
fi
_ccwgroup_dir=$_tmp_status_dir
fi
if [ -e ${_ccw_dir}/${QETH_DATA_CHAN}/group_device ] ; then
_tmp_status_dir=$(cd -P ${_ccw_dir}/${QETH_DATA_CHAN}/group_device; echo $PWD)
if [ "$_ccwgroup_dir" ] && [ "$_ccwgroup_dir" != "$_tmp_status_dir" ] ; then
mesg "CCW devices grouped to different devices"
exit 8
fi
_ccwgroup_dir=$_tmp_status_dir
fi
if [ -z "$_ccwgroup_dir" ] ; then
echo "$QETH_READ_CHAN,$QETH_WRITE_CHAN,$QETH_DATA_CHAN" > ${_ccw_groupdir}/drivers/${CCW_DRV}/group
if [ -e ${_ccw_dir}/${QETH_READ_CHAN}/group_device ] ; then
_ccwgroup_dir=$(cd -P ${_ccw_dir}/${QETH_READ_CHAN}/group_device; echo $PWD)
fi
fi
if [ -z "$_ccwgroup_dir" -o ! -e "$_ccwgroup_dir" ] ; then
mesg "Could not group $CCW_DRV devices $QETH_READ_CHAN/$QETH_WRITE_CHAN/$QETH_DATA_CHAN"
exit 9
fi
CCW_CHAN_ID=${_ccwgroup_dir##*/}
read _online < $_ccwgroup_dir/online
if [ "$ONLINE" -eq 1 ]; then
# Check whether we need to do something
# We do not check for the value of CCW_CHAN_MODE, since we
# might want to switch back and forth between several modes
if test "$_online" -eq "0" ; then
# Set the portname
if [ "$QETH_PORTNAME" ]; then
mesg "(portname $QETH_PORTNAME) "
echo "$QETH_PORTNAME" > $_ccwgroup_dir/portname
fi
# Activate Layer2 support
if [ -w "$_ccwgroup_dir/layer2" ] ; then
if [ "$QETH_LAYER2_SUPPORT" = "1" ]; then
mesg "(Layer2) "
echo 1 > $_ccwgroup_dir/layer2
else
echo 0 > $_ccwgroup_dir/layer2
fi
else
QETH_LAYER2_SUPPORT=
fi
# Enable IP address takeover
if [ "$QETH_IPA_TAKEOVER" ]; then
if [ "$QETH_IPA_TAKEOVER" = "1" ]; then
mesg "(IP takeover) "
echo 1 > $_ccwgroup_dir/ipa_takeover/enable
fi
fi
# Relative port number
if [ -w "$_ccwgroup_dir/portno" ] ; then
if [ -n "$QETH_PORTNO" ]; then
mesg "(Port $QETH_PORTNO) "
# This may fail, but trial and error is the only way to tell.
echo "$QETH_PORTNO" > $_ccwgroup_dir/portno
fi
else
unset QETH_PORTNO
fi
# Set additional options
if [ "$QETH_OPTIONS" ]; then
for opt in $QETH_OPTIONS; do
set -- $(IFS='='; echo $opt)
opt_name=$1
opt_val=$2
case "$opt_name" in
portname|ipa_takeover|layer2)
# These options are set above
debug_mesg "Invalid option $opt_name"
;;
*)
if [ "$opt_name" -a "$opt_val" ]; then
if [ -w "$_ccwgroup_dir/$opt_name" ]; then
mesg "($opt_name) "
echo "$opt_val" > $_ccwgroup_dir/$opt_name
if [ $? -eq 0 ] ; then
cur_opts="$cur_opts ${opt_name}=${opt_val}"
fi
else
# Skip invalid options
debug_mesg "Invalid option $opt_name"
fi
fi
;;
esac
done
# Update options list
QETH_OPTIONS="$cur_opts"
fi
echo "1" > $_ccwgroup_dir/online 2> /dev/null
# Re-read device status
read _ccw_dev_status < $_ccwgroup_dir/online
if [ "$_ccw_dev_status" -eq 0 ]; then
mesg "Could not set device ${CCW_CHAN_ID} online"
exit 10
fi
else
debug_mesg "Device ${CCW_CHAN_ID} is already online"
fi
else
if [ "$_online" -eq 1 ]; then
# Set the device offline
debug_mesg "Setting device offline"
echo "$ONLINE" > $_ccwgroup_dir/online
# Re-read to check whether we have succeeded
_online=$(cat $_ccwgroup_dir/online)
if [ "$_online" -ne "$ONLINE" ]; then
mesg "Could not set device ${CCW_CHAN_ID} offline"
exit 11
fi
else
debug_mesg "Device ${CCW_CHAN_ID} is already offline"
fi
echo 1 > $_ccwgroup_dir/ungroup
fi
else
CCW_CHAN_ID=$QETH_READ_CHAN
fi # QETH_FORCE
if [ $DEBUG = "no" ]; then
RULES_DIR=/etc/udev/rules.d
else
RULES_DIR=.
fi
RULES_FILE=51-${QETH_CARD}-${CCW_CHAN_ID}.rules
if [ -d "$RULES_DIR" ]; then
if [ -f ${RULES_DIR}/${RULES_FILE} ]; then
rm -f ${RULES_DIR}/${RULES_FILE}
fi
remove_channel_for_cio "${QETH_READ_CHAN}"
remove_channel_for_cio "${QETH_WRITE_CHAN}"
remove_channel_for_cio "${QETH_DATA_CHAN}"
if [ "$ONLINE" -eq "1" ]; then
add_channel_for_cio "${QETH_READ_CHAN},${QETH_WRITE_CHAN},${QETH_DATA_CHAN}"
# Write a new udev rules file
cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configure ${QETH_CARD} device at ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_DATA_CHAN}
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_READ_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_WRITE_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$QETH_DATA_CHAN", IMPORT{program}="collect $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_READ_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_WRITE_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
ACTION=="remove", SUBSYSTEM=="ccw", KERNEL=="$QETH_DATA_CHAN", IMPORT{program}="collect --remove $CCW_CHAN_ID %k $QETH_READ_CHAN $QETH_WRITE_CHAN $QETH_DATA_CHAN $CCW_DRV"
TEST=="[ccwgroup/${CCW_CHAN_ID}]", GOTO="${QETH_CARD}-${CCW_CHAN_ID}-end"
ACTION=="add", SUBSYSTEM=="ccw", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[drivers/ccwgroup:$CCW_DRV]group}="$QETH_READ_CHAN,$QETH_WRITE_CHAN,$QETH_DATA_CHAN"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="$CCW_DRV", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[drivers/ccwgroup:$CCW_DRV]group}="$QETH_READ_CHAN,$QETH_WRITE_CHAN,$QETH_DATA_CHAN"
LABEL="${QETH_CARD}-${CCW_CHAN_ID}-end"
EOF
if [ "$QETH_PORTNAME" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{portname}="$QETH_PORTNAME"
EOF
fi
if [ "$QETH_PORTNO" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{portno}="$QETH_PORTNO"
EOF
fi
if [ "$QETH_LAYER2_SUPPORT" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{layer2}="1"
EOF
elif [ "${QETH_CARD}" != "osn" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{layer2}="0"
EOF
fi
if [ "$QETH_IPA_TAKEOVER" ]; then
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{ipa_takeover/enable}="1"
EOF
fi
for opt in $QETH_OPTIONS; do
set -- $(IFS='='; echo $opt)
opt_name=$1
opt_val=$2
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{$opt_name}="$opt_val"
EOF
done
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", SUBSYSTEM=="ccwgroup", KERNEL=="$CCW_CHAN_ID", ATTR{online}="1"
EOF
fi
fi
udevadm settle
exit 0

161
qeth_configure.8 Normal file
View File

@ -0,0 +1,161 @@
.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
.I /etc/udev/rules.d/51-hsi-<ccwid>.rules
.RE
.I /etc/udev/rules.d/51-osn-<ccwid>.rules
.RE
.I /etc/udev/rules.d/51-qeth-<ccwid>.rules
.RS
These files provide the udev rules necessary to activate a specific 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 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 No device ${QETH_READ_CHAN}
.RS
A non-existent <ccwid> was specified for the read_channel parameter. Remember the x.y.ssss format is necessary. Return code 3 is set.
.RE
.IP
.B No device ${QETH_WRITE_CHAN}
.RS
A non-existent <ccwid> was specified for the write_channel parameter. Remember the x.y.ssss format is necessary. Return code 4 is set.
.RE
.IP
.B No device ${QETH_DATA_CHAN}
.RS
A non-existent <ccwid> was specified for the data_channel parameter. Remember the x.y.ssss format is necessary. Return code 4 is set.. Return code 5 is st.
.RE
.IP
.B Only qeth, hsi and osn are supported.
.RS
The device type specified by the -t option is not one of the supported types. Return code 6 is set.
.RE
.IP
.B Not a valid QETH device (cu $_cutype, dev $_devtype)
.RS
The device number specified does not correspond to a valid QETH device type. Return code 6 is set.
.RE
.IP
.B Could not load module ${CCW_DRV}
.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
Two or more of the read, write and 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_DRV devices $QETH_READ_CHAN/$QETH_WRITE_CHAN/$QETH_DATA_CHAN
.RS
The attempt to group the read, write and data 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 QETH device ${QETH_READ_CHAN}/${QETH_WRITE_CHAN}/${QETH_DATA_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 No portname required for $QETH_CARD adapters
.RS
If a QETH_CARD type other than "qeth" is specified or detected, a portname is not used, so using the -p option is unnecessary.
.RE
.IP
.B Invalid option $opt_name
.RS
Either portname, ipa_takeover, layer2, or a completely unknown QETH parameter was specified via the -o parameter. For portname, ipa_takeover, and layer2, use the -p, -i, or -l options, respectively.
.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.

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.

426
read_values.c Normal file
View File

@ -0,0 +1,426 @@
/********************************************************************************/
/* */
/* Copyright (C) 2014-2015, 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 <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 2015-10-12 13:31";
static char *version = "1.0.0";
void *configuration_handle = NULL;
int layers = -1;
/*
* List of machine types
*/
struct machinetype {
char *typenumber;
char *fullname;
} machinetypes[] = {
{ "2064", "2064 = z900 IBM eServer zSeries 900" },
{ "2066", "2066 = z800 IBM eServer zSeries 800" },
{ "2084", "2084 = z990 IBM eServer zSeries 990" },
{ "2086", "2086 = z890 IBM eServer zSeries 890" },
{ "2094", "2094 = z9-EC IBM System z9 Enterprise Class" },
{ "2096", "2096 = z9-BC IBM System z9 Business Class" },
{ "2097", "2097 = z10-EC IBM System z10 Enterprise Class" },
{ "2098", "2098 = z10-BC IBM System z10 Business Class" },
{ "2817", "2817 = z196 IBM zEnterprise 196" },
{ "2818", "2818 = z114 IBM zEnterprise 114" },
{ "2827", "2827 = z12-EC IBM zEnterprise EC12" },
{ "2828", "2828 = z12-BC IBM zEnterprise BC12" },
{ "2964", "2964 = z13 IBM z13" },
};
int debug = 0;
/******************************************************************************/
/* */
/* */
/* */
/******************************************************************************/
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 {
printf("Fehler: erg = %d, result_string = %s \n", erg, (result_string == NULL? "NULL": result_string));
/* 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;
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 (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("Sequence Code", 0, qc_sequence_code, string, WITH_KEY);
print_attribute("CPUs Total", 0, qc_num_cpu_total, integer, WITH_KEY);
print_attribute("CPUs IFL", 0, qc_num_cpu_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_cpu_total, integer, WITH_KEY);
print_attribute("LPAR CPUs IFL", 1, qc_num_cpu_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 */
/******************************************************************************/
/* */
/* print out the uuid for this machine */
/* */
/* TODO! */
/* */
/******************************************************************************/
void print_uuid()
{
return;
} /* 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_uuid */
/******************************************************************************/
/* */
/* 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\
-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_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_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:suV")) != -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 '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 + list_attr + create_scc + create_uuid) > 1) {
fputs("Only one of the options a, c, L, s or u can be specified.",stderr);
return 1;
} /* endif */
/* still not im[plemented thatfore set to zero */
create_uuid = 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 (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) {
print_uuid();
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;
} /* 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,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6f4e9d6f27cfad77ff84ac7a332a7fb2e17b620b3c2da4fc2ba47d2c77c94287
size 814967

3
s390-tools-rpmlintrc Normal file
View File

@ -0,0 +1,3 @@
addFilter("statically-linked-binary /usr/lib/s390-tools/.*")
addFilter("statically-linked-binary /usr/bin/read_values")
addFilter("systemd-service-without-service_.* *@.service")

View File

@ -0,0 +1,26 @@
--- a/etc/udev/rules.d/59-dasd.rules 2016-03-17 06:15:01.000000000 -0400
+++ b/etc/udev/rules.d/59-dasd.rules 2016-03-23 17:36:26.000000000 -0400
@@ -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 deadline

View File

@ -0,0 +1,57 @@
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 | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/fdasd/fdasd.c b/fdasd/fdasd.c
index 4503d3e..f04dc3d 100644
--- a/fdasd/fdasd.c
+++ b/fdasd/fdasd.c
@@ -826,7 +826,7 @@ fdasd_check_conffile_input (fdasd_anchor_t *anc,
* Verifies the specified block device.
*/
static void
-fdasd_verify_device (fdasd_anchor_t *anc, char *name)
+fdasd_verify_device (fdasd_anchor_t *anc, char *name)
{
struct stat dst;
char err_str[ERROR_STRING_SIZE];
@@ -847,7 +847,7 @@ fdasd_verify_device (fdasd_anchor_t *anc, char *name)
fdasd_error(anc, device_verification_failed, err_str);
}
- if (minor (dst.st_rdev) & PARTN_MASK) {
+ if (!anc->force_virtual && minor (dst.st_rdev) & PARTN_MASK) {
snprintf(err_str, ERROR_STRING_SIZE,
"Partition '%s' (%d/%d) detected where device is "
"required\n", name,
@@ -1156,9 +1156,12 @@ fdasd_reread_partition_table (fdasd_anchor_t *anc)
}
if (ioctl(fd, BLKRRPART, NULL) != 0) {
- close(fd);
- fdasd_error(anc, unable_to_ioctl, "Error while rereading "
- "partition table.\nPlease reboot!");
+ if (errno == EINVAL && !anc->force_virtual) {
+ close(fd);
+ fdasd_error(anc, unable_to_ioctl,
+ "Error while rereading "
+ "partition table.\nPlease reboot!");
+ }
}
close(fd);
}
--
1.8.5.2

View File

@ -0,0 +1,526 @@
--- s390-tools-1.34.0/dasdfmt/dasdfmt.8 2016-04-14 16:43:51.000000000 -0400
+++ s390-tools-1.34.0/dasdfmt/dasdfmt.8 2016-04-14 16:35:01.000000000 -0400
@@ -3,11 +3,11 @@
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] [-m \fIstep\fR]
.br
- [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
+ [-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR] [-P maxpar]
.br
- [-L] [-V] [-F] [-k] [-C] \fIdevice\fR
+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR ...
.SH DESCRIPTION
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
@@ -91,7 +91,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.
@@ -123,6 +123,20 @@
and always be a power of two. The recommended blocksize is 4096 bytes.
.TP
+\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 processes
+which is independent of the overall number of disks to be formatted as
+specified on the commandline. The maximum value for \fInumdisks\fR is
+1024. 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
\fB-l\fR \fIvolser\fR or \fB--label\fR=\fIvolser\fR
Specify the volume serial number or volume identifier to be written
to disk after formatting. If no label is specified, a sensible default
--- s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:43:51.000000000 -0400
+++ s390-tools-1.34.0/dasdfmt/dasdfmt.h 2016-04-14 16:35:01.000000000 -0400
@@ -195,6 +195,7 @@
#define LABEL_LENGTH 14
#define VLABEL_CHARS 84
#define LINE_LENGTH 80
+#define MAX_DEVICES 1024
#define ERR_LENGTH 90
#define DEFAULT_BLOCKSIZE 4096
@@ -214,7 +215,7 @@
if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
"is in invalid format\n",prog_name);}
-#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFkC"
+#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpQLtyvVFkCYP:"
static struct option dasdfmt_getopt_long_options[]=
{
@@ -225,12 +226,14 @@
{ "force", 0, 0, 'F'},
{ "progressbar", 0, 0, 'p'},
{ "hashmarks", 1, 0, 'm'},
- { "percentage", 0, 0, 'P'},
+ { "percentage", 0, 0, 'Q'},
{ "label", 1, 0, 'l'},
{ "device", 1, 0, 'f'},
{ "blocksize", 1, 0, 'b'},
{ "requestsize", 1, 0, 'r'},
{ "help", 0, 0, 'h'},
+ { "max_parallel",1, 0, 'P'},
+ { "yast_mode", 0, 0, 'Y'},
{ "keep_volser", 0, 0, 'k'},
{ "norecordzero", 0, 0, 'z'},
{ "check_host_count", 0, 0, 'C'},
@@ -267,6 +270,8 @@
int device_id;
int keep_volser;
int force_host;
+ int yast_mode;
+ int procnum;
} dasdfmt_info_t;
--- s390-tools-1.34.0/dasdfmt/dasdfmt.c 2016-04-14 16:43:51.000000000 -0400
+++ s390-tools-1.34.0/dasdfmt/dasdfmt.c 2016-04-14 16:35:01.000000000 -0400
@@ -17,6 +17,7 @@
#include "vtoc.h"
#include "util_proc.h"
#include "dasd_sys.h"
+#include <sys/wait.h>
#define BUSIDSIZE 8
@@ -48,7 +49,7 @@
*/
static void exit_usage(int exitcode)
{
- printf("Usage: %s [-htvypPLVFkC]\n"
+ printf("Usage: %s [-htvypQLVFkC]\n"
" [-l <volser> | --label=<volser>]\n"
" [-b <blocksize> | --blocksize=<blocksize>]\n"
" [-d <disk layout> | --disk_layout=<disk layout>]\n"
@@ -59,7 +60,7 @@
" -V or --version means print version\n"
" -L or --no_label means don't write disk label\n"
" -p or --progressbar means show a progress bar\n"
- " -P or --percentage means show a progress in percent\n"
+ " -Q or --percentage means show a progress in percent\n"
" -m x or --hashmarks=x means show a hashmark every x "
"cylinders\n"
" -r x or --requestsize=x means use x cylinders in one "
@@ -143,22 +144,33 @@
/*
* check given device name for blanks and some special characters
*/
-static void get_device_name(dasdfmt_info_t *info, char *name, int argc, char * argv[])
+static char* getdev(char* sysfs_path)
{
- struct util_proc_dev_entry dev_entry;
- struct stat dev_stat;
-
- if (info->node_specified && (info->device_id < argc))
- ERRMSG_EXIT(EXIT_MISUSE,"%s: Device can only specified once!\n",
- prog_name);
+ DIR* d;
+ struct dirent* de;
+
+ d = opendir(sysfs_path);
+ if(!d) ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not open directory %s.\n",prog_name,sysfs_path);
+ while((de = readdir(d)))
+ {
+ if(strncmp(de->d_name,"block:",6) == 0)
+ {
+ closedir(d);
+ return de->d_name+6;
+ }
+ }
+ return 0;
+}
- if (!info->node_specified && (info->device_id >= argc))
- ERRMSG_EXIT(EXIT_MISUSE,"%s: No device specified!\n",
- prog_name);
+static void get_device_name(dasdfmt_info_t *info, char *name)
+{
+ struct util_proc_dev_entry dev_entry;
+ struct stat dev_stat;
+ char buf[PATH_MAX];
+ char devno[9];
+ char* device;
+ int i;
- if (info->device_id < argc) {
- strcpy(info->devname, argv[info->device_id]);
- } else {
if ((strchr(name, ' ') != NULL)||(strchr(name, '#') != NULL)||
(strchr(name, '[') != NULL)||(strchr(name, ']') != NULL)||
(strchr(name, '!') != NULL)||(strchr(name, '>') != NULL)||
@@ -169,9 +181,38 @@
"blanks or special characters!\n",
prog_name);
- strncpy(info->devname, name, PATH_MAX - 1);
+ if (isxdigit(name[0]) && name[1] == '.' && isxdigit(name[2]) && name[3] == '.' && strlen(name) == 8)
+ { /* x.x.xxxx format */
+ for(i=0; i<8; i++)
+ devno[i] = tolower(name[i]);
+ devno[8] = 0;
+ sprintf(buf,"/sys/bus/ccw/devices/%s",devno);
+ device = getdev(buf);
+ if(device)
+ {
+ strcpy(info->devname,"/dev/");
+ strcat(info->devname,device);
+ }
+ else ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not find device file for device no. %s\n",prog_name,name);
+ }
+ else if (isxdigit(name[0]) && isxdigit(name[1]) && isxdigit(name[2]) && isxdigit(name[3]))
+ { /* xxxx format */
+ for(i=0; i<4; i++)
+ devno[i] = tolower(name[i]);
+ devno[4] = 0;
+ sprintf(buf,"/sys/bus/ccw/devices/0.0.%s",devno);
+ device = getdev(buf);
+ if(device)
+ {
+ strcpy(info->devname,"/dev/");
+ strcat(info->devname,device);
+ }
+ else ERRMSG_EXIT(EXIT_FAILURE,"%s: Could not find device file for device no. %s\n",prog_name,name);
+ }
+ else
+ strncpy(info->devname, name, PATH_MAX - 1);
+
info->devname[PATH_MAX - 1] = '\0';
- }
if (stat(info->devname, &dev_stat) != 0)
ERRMSG_EXIT(EXIT_MISUSE,
@@ -217,8 +258,9 @@
info->reqsize_specified = 0;
info->node_specified = 0;
info->device_id = 0;
- info->keep_volser = 0;
+ info->keep_volser = 0;
info->force_host = 0;
+ info->yast_mode = 0;
}
@@ -271,7 +313,6 @@
}
-
/*
* check the volume serial for special
* characters and move blanks to the end
@@ -640,7 +681,7 @@
info->hashstep = 10;
}
- printf("Printing hashmark every %d cylinders.\n",
+ if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n",
info->hashstep);
}
@@ -649,7 +690,7 @@
k = 0;
cyl = 1;
- if (info->print_progressbar || info->print_hashmarks)
+ if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
printf("\n");
while (1) {
@@ -688,7 +729,7 @@
if (info->print_hashmarks)
if ((cyl / info->hashstep - hashcount) != 0) {
- printf("#");
+ printf("%d|",info->procnum);
fflush(stdout);
hashcount++;
}
@@ -709,7 +750,7 @@
break;
}
- if (info->print_progressbar || info->print_hashmarks)
+ if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
printf("\n\n");
}
@@ -884,17 +925,21 @@
dasdfmt_prepare_and_format(info, cylinders, heads, p);
- printf("Finished formatting the device.\n");
+ if (!info->yast_mode)
+ printf("Finished formatting the device.\n");
if (!info->writenolabel)
dasdfmt_write_labels(info, vlabel, cylinders, heads);
- printf("Rereading the partition table... ");
+ if (!info->yast_mode)
+ printf("Rereading the partition table... ");
if (reread_partition_table()) {
ERRMSG("%s: error during rereading the partition "
"table: %s.\n", prog_name, strerror(errno));
- } else
- printf("ok\n");
+ } else {
+ if (!info->yast_mode)
+ printf("ok\n");
+ }
}
}
@@ -905,7 +950,8 @@
volume_label_t vlabel;
char old_volser[7];
- char dev_filename[PATH_MAX];
+ char* dev_filename[MAX_DEVICES];
+ int dev_count=0;
char str[ERR_LENGTH];
char buf[7];
@@ -913,7 +959,10 @@
char *reqsize_param_str = NULL;
char *hashstep_str = NULL;
- int rc, index;
+ int rc, index, i;
+
+ int max_parallel=1;
+ int running=0;
/* Establish a handler for interrupt signals. */
signal (SIGTERM, program_interrupt_signal);
@@ -990,7 +1039,7 @@
}
break;
- case 'P':
+ case 'Q':
if (!(info.print_hashmarks || info.print_progressbar))
info.print_percentage = 1;
break;
@@ -1034,9 +1083,18 @@
info.reqsize_specified = 1;
break;
case 'f' :
- strncpy(dev_filename, optarg, PATH_MAX);
+ if(dev_count>=MAX_DEVICES)
+ ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n",
+ prog_name);
+ dev_filename[dev_count++]=strdup(optarg);
info.node_specified=1;
break;
+ case 'Y' : /* YaST mode */
+ info.yast_mode=1;
+ break;
+ case 'P' : /* max parallel formatting processes */
+ max_parallel=atoi(optarg);
+ break;
case 'k' :
info.keep_volser=1;
break;
@@ -1059,58 +1117,147 @@
CHECK_SPEC_MAX_ONCE(info.labelspec, "label");
CHECK_SPEC_MAX_ONCE(info.writenolabel, "omit-label-writing flag");
- if (info.blksize_specified)
- PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
- "blocksize");
- if (info.reqsize_specified) {
- PARSE_PARAM_INTO(reqsize, reqsize_param_str, 10, "requestsize");
- if (reqsize < 1 || reqsize > 255)
- ERRMSG_EXIT(EXIT_FAILURE,
- "invalid requestsize %d specified\n",
- reqsize);
- } else
- reqsize = DEFAULT_REQUESTSIZE;
- if (info.print_hashmarks)
- PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep");
-
- get_device_name(&info, dev_filename, argc, argv);
+ while(info.device_id < argc) { /* devices specified at the end of cmdline */
+ if(dev_count>=MAX_DEVICES)
+ ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n",
+ prog_name);
+ dev_filename[dev_count++]=strdup(argv[info.device_id]);
+ info.node_specified=1;
+ info.device_id++;
+ }
- if (!info.blksize_specified)
- format_params = ask_user_for_blksize(format_params);
+ if (info.node_specified == 0)
+ ERRMSG_EXIT(EXIT_MISUSE,"%s: No device specified!\n",
+ prog_name);
if (info.keep_volser) {
if(info.labelspec) {
ERRMSG_EXIT(EXIT_MISUSE,"%s: The -k and -l options are mutually exclusive\n",
prog_name);
}
- if(!(format_params.intensity & DASD_FMT_INT_COMPAT)) {
- printf("WARNING: VOLSER cannot be kept " \
- "when using the ldl format!\n");
- exit(1);
+ }
+
+ if (info.labelspec && max_parallel > 1) {
+ ERRMSG_EXIT(EXIT_MISUSE,"%s: The -l option cannot be used with parallel formatting\n",
+ prog_name);
+ }
+
+ if(info.yast_mode) {
+ for(i=0;i<dev_count;i++) {
+ dasd_information_t dasd_info;
+ struct dasd_eckd_characteristics *characteristics;
+ unsigned int cylinders;
+
+ get_device_name(&info, dev_filename[i]);
+ if ((filedes = open(info.devname, O_RDWR)) == -1) {
+ ERRMSG("%s: Unable to open device %s: %s\n",
+ prog_name, info.devname, strerror(errno));
+ free(dev_filename[i]);
+ dev_filename[i]=(char*)-1; /* ignore device */
+ continue;
+ }
+ if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) "
+ "IOCTL BIODASDINFO failed (%s).\n",
+ prog_name, strerror(errno));
+ free(dev_filename[i]);
+ dev_filename[i]=(char*)-1; /* ignore device */
+ close(filedes);
+ continue;
+ }
+
+ 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;
+
+ printf("%d\n", cylinders);
+ close(filedes);
}
-
- if(dasdfmt_get_volser(info.devname, old_volser) == 0)
- vtoc_volume_label_set_volser(&vlabel, old_volser);
- else
- ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n",
- prog_name, info.devname);
-
+ fflush(stdout);
}
- if ((filedes = open(info.devname, O_RDWR)) == -1)
- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
- prog_name, info.devname, strerror(errno));
+ /* fork one formatting process for each device */
+ rc = 0;
+ for(i=0;i<dev_count;i++) {
+ int chpid; /* child process ID */
+ int tmp;
- check_disk(&info);
+ if(dev_filename[i]==(char*)-1) continue; /* ignore device */
- if (check_param(str, ERR_LENGTH, &format_params) < 0)
- ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
+ chpid=fork();
+ if(chpid==-1)
+ ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to create child process: %s\n",
+ prog_name, strerror(errno));
- do_format_dasd(&info, &format_params, &vlabel);
+ if(!chpid) {
+ info.procnum=i;
+ if (info.blksize_specified)
+ PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
+ "blocksize");
+ if (info.reqsize_specified) {
+ PARSE_PARAM_INTO(reqsize, reqsize_param_str, 10, "requestsize");
+ if (reqsize < 1 || reqsize > 255)
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "invalid requestsize %d specified\n",
+ reqsize);
+ } else
+ reqsize = DEFAULT_REQUESTSIZE;
+ if (info.print_hashmarks)
+ PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep");
+
+ get_device_name(&info, dev_filename[i]);
+
+ if (!info.blksize_specified)
+ format_params = ask_user_for_blksize(format_params);
+
+ if (info.keep_volser) {
+ if(format_params.intensity == 0x00) {
+ printf("WARNING: VOLSER cannot be kept " \
+ "when using the ldl format!\n");
+ exit(1);
+ }
- if (close(filedes) != 0)
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
- prog_name, strerror(errno));
+ if(dasdfmt_get_volser(info.devname, old_volser) == 0)
+ vtoc_volume_label_set_volser(&vlabel, old_volser);
+ else
+ ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n",
+ prog_name, info.devname);
- return 0;
+ }
+
+ if ((filedes = open(info.devname, O_RDWR)) == -1)
+ ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
+ prog_name, info.devname, strerror(errno));
+
+ check_disk(&info);
+
+ if (check_param(str, ERR_LENGTH, &format_params) < 0)
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
+
+ do_format_dasd(&info, &format_params, &vlabel);
+
+ if (close(filedes) != 0)
+ ERRMSG("%s: error during close: %s\ncontinuing...\n",
+ prog_name, strerror(errno));
+
+ exit(0);
+ } else {
+ running++;
+ if(running>=max_parallel) {
+ if(wait(&tmp) > 0 && WEXITSTATUS(tmp))
+ rc = WEXITSTATUS(tmp);
+ running--;
+ }
+ }
+ }
+
+ /* wait until all formatting children have finished */
+ while(wait(&i) > 0)
+ if (WEXITSTATUS(i)) rc = WEXITSTATUS(i);
+
+ return rc;
}

View File

@ -0,0 +1,175 @@
From c261ec990a8259f2540089827309b918e1c31590 Mon Sep 17 00:00:00 2001
From: Hannes Reinecke <hare@suse.de>
Date: Fri, 22 Nov 2013 15:34:22 +0100
Subject: [PATCH 5/8] dumpconf: Use compatible sysconfig layout
SUSE is quite restrictive on how the sysconfig
should look like.
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
etc/sysconfig/dumpconf | 134 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 93 insertions(+), 41 deletions(-)
diff --git a/etc/sysconfig/dumpconf b/etc/sysconfig/dumpconf
index a3639cf..76f9040 100644
--- a/etc/sysconfig/dumpconf
+++ b/etc/sysconfig/dumpconf
@@ -1,61 +1,113 @@
+## 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
#
-# s390 dump config
-#
-# Configures the actions which should be performed after a kernel panic
-# and on PSW restart.
+# Define the action that should be taken if a panic happens.
#
# The following actions are supported:
#
-# * stop: Stop Linux (default)
-# * dump: Dump Linux with stand-alone dump tool
-# * vmcmd: Issue z/VM CP commands
-# * reipl: Re-IPL Linux using setting under /sys/firmware/reipl
-# * dump_reipl: First dump Linux with stand-alone dump tool, then re-IPL Linux
-# using setting under /sys/firmware/reipl
+# * stop: Stop Linux (default)
+# * dump: Dump Linux
+# * vmcmd: Issue z/VM CP commands
+# * reipl: Re-IPL Linux using setting under /sys/firmware/reipl
+# * dump_reipl: First dump Linux, then re-IPL Linux using setting under
+# /sys/firmware/reipl
#
+ON_PANIC="stop"
-# For the actions "reipl" and "dump_reipl" the DELAY_MINUTES keyword may
-# be used to delay the activation of dumpconf.
-# Thus potential reipl loops caused by kernel panics
-# which persistently occur early in the boot process can be prevented.
+## 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"
-# Dump on CCW device (DASD) and re-IPL after dump is complete.
-# The re-IPL device, as specified under "/sys/firmware/reipl", is used.
-# The activation of dumpconf is delayed by 5 minutes.
+## Type: list(ccw,fcp)
+## Default: ""
+## ServiceRestart: dumpconf
+#
+# Define the type, ccw for DASD and fcp for zFCP.
#
-# ON_PANIC=dump_reipl
-# DUMP_TYPE=ccw
-# DEVICE=0.0.4e13
-# DELAY_MINUTES=5
+DUMP_TYPE=""
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
#
-# Dump on fcp device (SCSI Disk)
+# Define the device id for a DASD or SCSI over zFCP dump device.
#
-# ON_PANIC=dump
-# DUMP_TYPE=fcp
-# DEVICE=0.0.4711
-# WWPN=0x5005076303004711
-# LUN=0x4711000000000000
-# BOOTPROG=0
-# BR_LBA=0
+# 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.
#
-# Use VMDUMP
+# For example: WWPN=0x5005076303004711
#
-# ON_PANIC=vmcmd
-# VMCMD_1="MESSAGE * Starting VMDUMP"
-# VMCMD_2="VMDUMP"
-# VMCMD_3="IPL 4711"
+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.
#
-# Stop Linux (default)
+# 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.
#
-# ON_PANIC=stop
+BR_LBA="0"
+## Type: string
+## Default: ""
+## ServiceRestart: dumpconf
#
-# Re-IPL Linux
-# The re-IPL device, as specified under "/sys/firmware/reipl", is used.
-# Since the DELAY_MINUTES keyword is omitted, there is no delay and
-# dumpconf becomes active immediately during system startup.
+# 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.
#
-# ON_PANIC=reipl
+VMCMD_1=""
+VMCMD_2=""
+VMCMD_3=""
+VMCMD_4=""
+VMCMD_5=""
+VMCMD_6=""
+VMCMD_7=""
+VMCMD_8=""
--
1.8.1.4

View File

@ -0,0 +1,31 @@
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 8/8] 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,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}"
--
1.8.1.4

View File

@ -0,0 +1,13 @@
--- s390-tools-1.24.1/zipl/boot/menu.c 2013-12-18 11:11:45.000000000 -0500
+++ s390-tools-1.24.1/zipl/boot/menu.c 2013-12-18 11:59:18.000000000 -0500
@@ -166,7 +166,9 @@
menu_list();
if (is_zvm())
- printf("Note: VM users please use '#cp vi vmsg <input>'\n");
+ 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,35 @@
Subject: [PATCH] [BZ 141695] chiucvallow: correct verification return code
From: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Description: chiucvallow: correct verification return code
Symptom: When running test_chiucvallow.sh, the script is
failing to validate filter files with special
characters.
because the chiucvallow.in -V is
Problem: The chiucvallow -V is returning code 2 and for
this reason, the script gives an error message,
but the filter file is validated successfully
manually.
Solution: Correct the return code of chiucvallow to handle
verification failures correctly.
Reproduction: See Symptom.
Upstream-ID: -
Problem-ID: 141695
Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
---
iucvterm/bin/chiucvallow.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/iucvterm/bin/chiucvallow.in
+++ b/iucvterm/bin/chiucvallow.in
@@ -115,7 +115,8 @@ verify_filter(){
printf "\n$PRG: Verification summary: verified=%d failed=%d size=%d bytes\n" \
$count $failed $fsize
- return 2
+
+ test $failed -eq 0 || return 2
}
#

View File

@ -0,0 +1,49 @@
Subject: [PATCH] [BZ 143839] chreipl/virtio: fix chreipl node for virtio-blk disks
From: Christian Borntraeger <borntraeger@de.ibm.com>
Description: chreipl/virtio: fix chreipl node for virtio-blk disks
Symptom: chreipl node <mount point> for a virtio-blk disk fails:
Could not find DASD CCW device "virtio1"
Problem: The sysfs walking code to resolve the device is not
handling virtio devices correctly.
Solution: Use the realpath of the device to get the busid for all
supported devices.
Reproduction: Run chreipl node <mountpoint> with virtio-blk devices as
backing for mount point.
Upstream-ID: -
Problem-ID: 143839
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
ipl_tools/ccw.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
--- a/ipl_tools/ccw.c
+++ b/ipl_tools/ccw.c
@@ -76,21 +76,19 @@ out_fclose:
static int ccw_busid_get_sysfs_new(const char *device, char *busid)
{
char path[PATH_MAX], buf[4096];
- char *ptr;
memset(buf, 0, sizeof(buf));
snprintf(path, sizeof(path), "/sys/block/%s/device", device);
- if (readlink(path, buf, sizeof(buf) - 1) == -1)
+ if (realpath(path, buf) == NULL)
return -1;
/*
* The output has the following format:
- * ../../../0.0.4e13
+ * /sys/devices/css0/0.0.0119/0.0.3f19/block/dasda
+ * /sys/devices/css0/0.0.0000/0.0.0000/virtio0/block/vda
*/
- ptr = strrchr(buf, '/');
- if (!ptr)
- ERR_EXIT("Could not read \"%s\"", path);
- strncpy(busid, ptr + 1, 9);
+ if (sscanf(buf, "/sys/devices/css0/%*[0-9a-f.]/%[0-9a-f.]", busid) != 1)
+ return -1;
return 0;
}

View File

@ -0,0 +1,32 @@
Subject: [PATCH] [BZ 147113] chzdev: Disable root device update mechanism
From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Description: chzdev: Disable root device update mechanism
Symptom: chzdev reports problems updating /etc/zipl.conf and running
zipl.
Problem: When chzdev changes the root device persistent configuration,
it performs additional steps to ensure that these changes are
correctly applied. Example for such steps are: updating the
initial RAM disk, modifying the zipl.conf configuration file
and running zipl. As these steps are incompatible with the target
distribution, they fail.
Solution: Suppress chzdev's root device update mechanism.
Reproduction: chzdev --enable --persistent --by-path /
Upstream-ID: -
Problem-ID: 147113
Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
---
zdev/src/chzdev.c | 1 +
1 file changed, 1 insertion(+)
--- a/zdev/src/chzdev.c
+++ b/zdev/src/chzdev.c
@@ -233,6 +233,7 @@ static void init_options(struct options
opts->settings = strlist_new();
opts->remove = strlist_new();
opts->base = strlist_new();
+ opts->no_root_check = 1;
}
/* Release memory used in options data structure. */

View File

@ -0,0 +1,744 @@
Subject: [PATCH] [FEAT LS1213] dasd: add query host access to volume support
From: Stefan Haberland <sth@linux.vnet.ibm.com>
Summary: dasd: add query host access to volume support
Description: With this feature, applications can query if a DASD volume is
online to another operating system instances by checking the
online status of all attached hosts from the storage server.
Upstream-ID: -
Problem-ID: LS1213
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.8 | 7 ++
dasdfmt/dasdfmt.c | 38 ++++++++++++--
dasdfmt/dasdfmt.h | 4 +
fdasd/fdasd.8 | 9 ++-
fdasd/fdasd.c | 32 ++++++++++++
fdasd/fdasd.h | 28 +++++-----
include/libzds.h | 1
include/u2s.h | 5 +
libu2s/u2s.c | 43 ++++++++++++++++
libzds/Makefile | 2
libzds/libzds.c | 46 +++++++++++++++--
zconf/lsdasd | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
zconf/lsdasd.8 | 5 +
zdsfs/zdsfs.1 | 4 +
zdsfs/zdsfs.c | 18 ++++++
15 files changed, 345 insertions(+), 36 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -7,7 +7,7 @@ dasdfmt \- formatting of DASD (ECKD) dis
.br
[-r \fIcylinder\fR] [-b \fIblksize\fR] [-l \fIvolser\fR] [-d \fIlayout\fR]
.br
- [-L] [-V] [-F] [-k] \fIdevice\fR
+ [-L] [-V] [-F] [-k] [-C] \fIdevice\fR
.SH DESCRIPTION
\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
@@ -70,6 +70,11 @@ Print version number and exit.
Formats the device without checking, if the device is in use.
.TP
+\fB-C\fR or \fB--check_host_count\fR
+Force dasdfmt to check the host access open count to ensure the device
+is not online on another operating system instance
+
+.TP
\fB-d\fR \fIlayout\fR or \fB--disk_layout\fR=\fIlayout\fR
Formats the device with compatible disk layout or linux disk layout.
\fIlayout\fR is either \fIcdl\fR for the compatible disk layout
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -18,6 +18,8 @@
#include "util_proc.h"
#include "dasd_sys.h"
+#define BUSIDSIZE 8
+
/* Full tool name */
static const char tool_name[] = "dasdfmt: zSeries DASD format program";
@@ -46,7 +48,7 @@ print_version (void)
*/
static void exit_usage(int exitcode)
{
- printf("Usage: %s [-htvypPLVFk]\n"
+ printf("Usage: %s [-htvypPLVFkC]\n"
" [-l <volser> | --label=<volser>]\n"
" [-b <blocksize> | --blocksize=<blocksize>]\n"
" [-d <disk layout> | --disk_layout=<disk layout>]\n"
@@ -65,6 +67,9 @@ static void exit_usage(int exitcode)
" -v means verbose mode\n"
" -F means don't check if the device is in use\n"
" -k means keep volume serial\n"
+ " -C or --check_host_count means force dasdfmt to check\n"
+ " the host access open count to ensure the device\n"
+ " is not online on another operating system instance\n"
" --norecordzero prevent storage server from modifying"
" record 0\n\n"
" <volser> is the volume identifier, which is converted\n"
@@ -190,7 +195,6 @@ static void get_device_name(dasdfmt_info
}
}
-
/*
* initialize the dasdfmt info structure
*/
@@ -214,6 +218,7 @@ static void init_info(dasdfmt_info_t *in
info->node_specified = 0;
info->device_id = 0;
info->keep_volser = 0;
+ info->force_host = 0;
}
@@ -776,6 +781,7 @@ static void do_format_dasd(dasdfmt_info_
dasd_information_t dasd_info;
struct dasd_eckd_characteristics *characteristics;
unsigned int cylinders, heads;
+ int count;
if (info->verbosity > 0) printf("Retrieving disk geometry...\n");
@@ -835,6 +841,27 @@ static void do_format_dasd(dasdfmt_info_
if ((info->verbosity > 0) || (!info->withoutprompt))
dasdfmt_print_info(info, vlabel, cylinders, heads, p);
+ count = u2s_get_host_access_count(info->devname);
+ if (info->force_host) {
+ if (count > 1) {
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "\n%s: Disk %s is online on OS instances in %d different LPARs.\n"
+ "Note: Your installation might include z/VM systems that are configured to\n"
+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n",
+ prog_name, info->devname, count);
+ } else if (count < 0) {
+ ERRMSG("\nHosts access information not available for disk %s.\n\n",
+ info->devname);
+ return;
+ }
+ } else if (count > 1)
+ ERRMSG("\nWARNING:\n"
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
+ "Note: Your installation might include z/VM systems that are configured to\n"
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
+ info->devname, count);
+
if (!info->testmode) {
if (!info->withoutprompt) {
printf("\n--->> ATTENTION! <<---\n");
@@ -916,10 +943,6 @@ int main(int argc,char *argv[])
info.force=1;
break;
- case 'C':
- format_params.intensity |= DASD_FMT_INT_COMPAT;
- break;
-
case 'd' :
if (strncmp(optarg,"cdl",3)==0)
{
@@ -1017,6 +1040,9 @@ int main(int argc,char *argv[])
case 'k' :
info.keep_volser=1;
break;
+ case 'C':
+ info.force_host = 1;
+ break;
case -1:
/* End of options string - start of devices list */
info.device_id = optind;
--- a/dasdfmt/dasdfmt.h
+++ b/dasdfmt/dasdfmt.h
@@ -214,7 +214,7 @@ typedef struct format_data_t {
if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
"is in invalid format\n",prog_name);}
-#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFk"
+#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpPLtyvVFkC"
static struct option dasdfmt_getopt_long_options[]=
{
@@ -233,6 +233,7 @@ static struct option dasdfmt_getopt_long
{ "help", 0, 0, 'h'},
{ "keep_volser", 0, 0, 'k'},
{ "norecordzero", 0, 0, 'z'},
+ { "check_host_count", 0, 0, 'C'},
{0, 0, 0, 0}
};
@@ -265,6 +266,7 @@ typedef struct dasdfmt_info {
int node_specified;
int device_id;
int keep_volser;
+ int force_host;
} dasdfmt_info_t;
--- a/fdasd/fdasd.8
+++ b/fdasd/fdasd.8
@@ -4,11 +4,11 @@ fdasd \- partitioning tool.
.SH SYNOPSIS
interactive mode:
.br
- \fBfdasd\fR [-s] [-r] \fIdevice\fR
+ \fBfdasd\fR [-s] [-r] [-C] \fIdevice\fR
.br
command line mode:
.br
- \fBfdasd\fR [-s] [-r] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
+ \fBfdasd\fR [-s] [-r] [-C] {-a[-k|-l \fIvolser\fR]|-i|-p|-c \fIconf_file\fR}
[-f \fI[type,blocksize]\fR] \fIdevice\fR
.br
help:
@@ -131,6 +131,11 @@ In combination with the -s option fdasd
partition table.
.TP
+\fB-C\fR or \fB--check_host_count\fR
+Force fdasd to check the host access open count to ensure the device
+is not online on another operating system instance
+
+.TP
\fB-f\fR \fI[type,blocksize]\fR or \fB--force\fR \fI[type,blocksize]\fR
Force fdasd to work on non DASD devices.
.br
--- a/fdasd/fdasd.c
+++ b/fdasd/fdasd.c
@@ -369,7 +369,10 @@ fdasd_usage (void)
" found in CONFIGFILE\n"
"-i, --volser Print volume serial\n"
"-p, --table Print partition table\n"
- "-f, --force Force fdasd to work on non DASD devices\n");
+ "-f, --force Force fdasd to work on non DASD devices\n"
+ "-C, --check_host_count Force fdasd to check the host access\n"
+ " open count to ensure the device is not\n"
+ " online on another operating system instance\n");
}
@@ -572,6 +575,9 @@ fdasd_parse_options (fdasd_anchor_t *anc
anc->force_virtual++;
fdasd_parse_force_options(anc, optarg);
break;
+ case 'C':
+ anc->force_host++;
+ break;
case -1:
/* End of options string - start of devices list */
break;
@@ -824,6 +830,7 @@ fdasd_verify_device (fdasd_anchor_t *anc
{
struct stat dst;
char err_str[ERROR_STRING_SIZE];
+ int count;
if ((stat(name, &dst)) < 0 ) {
snprintf(err_str, ERROR_STRING_SIZE,
@@ -856,6 +863,29 @@ fdasd_verify_device (fdasd_anchor_t *anc
fdasd_error(anc, device_verification_failed, err_str);
}
+ count = u2s_get_host_access_count(name);
+ if (anc->force_host) {
+ if (count > 1) {
+ snprintf(err_str, ERROR_STRING_SIZE,
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
+ "Note: Your installation might include z/VM systems that are configured to\n"
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
+ name, count);
+ fdasd_error(anc, device_verification_failed, err_str);
+ } else if (count < 0) {
+ snprintf(err_str, ERROR_STRING_SIZE,
+ "Hosts access information not available for disk %s.\n",
+ name);
+ fdasd_error(anc, device_verification_failed, err_str);
+ }
+ } else if (count > 1)
+ printf("\nWARNING:\n"
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
+ "Note: Your installation might include z/VM systems that are configured to\n"
+ "automatically vary on disks, regardless of whether they are subsequently used.\n\n",
+ name, count);
+
if (anc->verbose)
printf("Verification successful for '%s' (%d/%d)\n", name,
(unsigned short) major(dst.st_rdev),
--- a/fdasd/fdasd.h
+++ b/fdasd/fdasd.h
@@ -157,22 +157,23 @@ struct dasd_eckd_characteristics {
#define PARTITION_GPFS 5
static struct option fdasd_long_options[] = {
- { "version", no_argument, NULL, 'v'},
- { "auto", no_argument, NULL, 'a'},
- { "silent", no_argument, NULL, 's'},
- { "verbose", no_argument, NULL, 'r'},
- { "label", required_argument, NULL, 'l'},
- { "config", required_argument, NULL, 'c'},
- { "help", no_argument, NULL, 'h'},
- { "table", no_argument, NULL, 'p'},
- { "volser", no_argument, NULL, 'i'},
- { "keep_volser", no_argument, NULL, 'k'},
- { "force", optional_argument, NULL, 'f'},
- { 0, 0, 0, 0 }
+ { "version", no_argument, NULL, 'v'},
+ { "auto", no_argument, NULL, 'a'},
+ { "silent", no_argument, NULL, 's'},
+ { "verbose", no_argument, NULL, 'r'},
+ { "label", required_argument, NULL, 'l'},
+ { "config", required_argument, NULL, 'c'},
+ { "help", no_argument, NULL, 'h'},
+ { "table", no_argument, NULL, 'p'},
+ { "volser", no_argument, NULL, 'i'},
+ { "keep_volser", no_argument, NULL, 'k'},
+ { "force", optional_argument, NULL, 'f'},
+ { "check_host_count", no_argument, NULL, 'C'},
+ { 0, 0, 0, 0 }
};
/* Command line option abbreviations */
-static const char option_string[] = "vasrl:c:hpikf::";
+static const char option_string[] = "vasrl:c:hpikf::C";
struct fdasd_options {
char *device;
@@ -214,6 +215,7 @@ typedef struct fdasd_anchor {
int print_volser;
int keep_volser;
int force_virtual;
+ int force_host;
int big_disk;
int silent;
int verbose;
--- a/include/libzds.h
+++ b/include/libzds.h
@@ -803,6 +803,7 @@ int lzds_zdsroot_extract_datasets_from_d
void lzds_DS1RECFM_to_recfm(char DS1RECFM, char *buffer);
+int lzds_analyse_open_count(struct zdsroot *root, int warn);
/** @} */ /* end of group libzds_functions_helper */
--- a/include/u2s.h
+++ b/include/u2s.h
@@ -13,7 +13,8 @@
#define U2S_BUS_ID_SIZE 32
-int
-u2s_getbusid(char * devicenode, char * busid);
+int u2s_getbusid(char *, char *);
+int u2s_read_attribute(char *, char *, char *, size_t);
+int u2s_get_host_access_count(char *);
#endif /* U2S_H */
--- a/libu2s/u2s.c
+++ b/libu2s/u2s.c
@@ -17,6 +17,7 @@
#include <fcntl.h>
#include <sys/sysmacros.h>
#include <dirent.h>
+#include <stdlib.h>
#include "u2s.h"
@@ -282,3 +283,45 @@ int u2s_getbusid(char *devicenode, char
return rc;
}
+
+/*
+ * Attempts to find the sysfs entry for the given busid and reads
+ * the contents of a specified attribute to the buffer
+ */
+int u2s_read_attribute(char *busid, char *attribute, char *buffer,
+ size_t count)
+{
+ char path[100];
+ int rc, fd;
+ ssize_t rcount;
+
+ rc = 0;
+ snprintf(path, sizeof(path), "/sys/bus/ccw/devices/%s/%s",
+ busid, attribute);
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return errno;
+ rcount = read(fd, buffer, count);
+ if (rcount < 0)
+ rc = errno;
+ close(fd);
+ return rc;
+}
+
+int u2s_get_host_access_count(char *devicenode)
+{
+ char busid[BUSIDSIZE];
+ unsigned long value;
+ char buffer[10];
+ char *endp;
+
+ u2s_getbusid(devicenode, busid);
+ u2s_read_attribute(busid, "host_access_count", buffer, sizeof(buffer));
+
+ value = strtoul(buffer, &endp, 0);
+
+ if (endp == buffer)
+ return -EINVAL;
+
+ return value;
+}
--- a/libzds/Makefile
+++ b/libzds/Makefile
@@ -8,7 +8,7 @@ CFLAGS += -D_FILE_OFFSET_BITS=64
all: libzds.a
-libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o
+libzds.a: libzds.o $(rootdir)/libutil/util_list.o $(rootdir)/libvtoc/vtoc.o $(rootdir)/libu2s/u2s.o
libzds.o: ../include/libzds.h
--- a/libzds/libzds.c
+++ b/libzds/libzds.c
@@ -29,6 +29,7 @@
#include "libzds.h"
#include "util.h"
+#include "u2s.h"
#include <malloc.h>
#include <linux/types.h>
@@ -72,6 +73,8 @@ struct errorlog {
*/
#define ERRORMSG 240
+#define BUSIDSIZE 8
+
/**
* @brief An internal structure that represents an entry in the error log.
*/
@@ -3760,15 +3763,46 @@ void lzds_DS1RECFM_to_recfm(char DS1RECF
*/
}
+int lzds_analyse_open_count(struct zdsroot *root, int warn)
+{
+ struct dasd *dasd;
+ int value;
+ int rc = 0;
+ util_list_iterate(root->dasdlist, dasd) {
+ value = u2s_get_host_access_count(dasd->device);
+ if (value < 0) {
+ fprintf(stderr,
+ "Hosts access information not available for disk %s.\n",
+ dasd->device);
+ rc = value;
+ continue;
+ }
+ if (value == 1)
+ continue;
+ if (warn)
+ fprintf(stderr,
+ "\nWARNING:\n"
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
+ "Note: Your installation might include z/VM systems that are configured to\n"
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
+ dasd->device, value);
+ else {
+ fprintf(stderr,
+ "\nERROR:\n"
+ "Disk %s is online on operating system instances in %d different LPARs.\n"
+ "Ensure that the disk is not being used by a system outside your LPAR.\n"
+ "Note: Your installation might include z/VM systems that are configured to\n"
+ "automatically vary on disks, regardless of whether they are subsequently used.\n",
+ dasd->device, value);
+ rc = -EACCES;
+ }
+ }
-
-
-
-
-
-
+ return rc;
+}
--- a/zconf/lsdasd
+++ b/zconf/lsdasd
@@ -30,6 +30,8 @@ function PrintUsage() {
Print old version of lsdasd output.
-l|--long
Print extended information about DASDs.
+ -H|--host-access-list
+ Print information about hosts accessing DASDs.
-v|--verbose
For compatibility/future use. Currently ignored.
--version
@@ -115,6 +117,33 @@ function listDASDDeviceDirectories() {
}
#------------------------------------------------------------------------------
+# find dasd directory in debugfs
+#------------------------------------------------------------------------------
+function findDASDDebugfsDirectorie() {
+ local mntentries
+
+ while read -a mntentries
+ do
+ if [[ "${mntentries[2]}" == "debugfs" ]]
+ then
+ DASD_DBF_DIR="${mntentries[1]}"
+ break;
+ fi
+ done < /etc/mtab
+ if [[ "$DASD_DBF_DIR" == "" ]]
+ then
+ echo "$CMD: No debugfs mount point found" >&2
+ exit 1
+ fi
+ DASD_DBF_DIR="$DASD_DBF_DIR/dasd"
+ if [[ ! -d "$DASD_DBF_DIR" ]]
+ then
+ echo "$CMD: Default DASD debugfs directory $DASD_DBF_DIR does not exist" >&2
+ exit 1
+ fi
+}
+
+#------------------------------------------------------------------------------
# gather device data and call appropriate output function
#------------------------------------------------------------------------------
function gatherDeviceData() {
@@ -197,6 +226,8 @@ function gatherDeviceData() {
extended
elif [[ "$PRINTUID" == "true" ]]; then
uid
+ elif [[ "$OUTPUT" == "host" ]]; then
+ host
else
newoutput
fi
@@ -527,6 +558,104 @@ function extended()
"${HPF_PATHS[@]}" ;
}
+function host()
+{
+findDASDDebugfsDirectorie
+
+if [[ ! -f "$DASD_DBF_DIR/$BUSID/host_access_list" ]]
+then
+ printf "\n%s: hosts access information not available\n" "$BUSID"
+ return
+fi
+
+local temp=`mktemp /tmp/lsdasd.XXXXXX`
+if test -w $temp ; then :; else
+ printf "\nCreating temporary file failed\n"
+ return
+fi
+
+cat $DASD_DBF_DIR/$BUSID/host_access_list > $temp 2> /dev/null
+ret=$?
+if [[ $ret -ne 0 ]]
+then
+ printf "%s: hosts access information not available\n" "$BUSID"
+ rm -f $temp
+ return $ret
+fi
+
+unset index
+unset array
+declare -a array
+
+index=(pgid status_flags sysplex_name supported_cylinder timestamp)
+
+for element in ${index[@]}
+do
+ count=0
+
+ declare -a $element
+ OLDIFS=$IFS
+ IFS=$'\n'
+ for value in `grep $element $temp`
+ do
+ (( ++count ))
+ value=$(echo -e $value | cut -d ' ' -f2)
+ eval $element[$count]=$value
+ done
+ IFS=$OLDIFS
+done
+
+printf "Host information for %s\n" "$BUSID";
+printf "Path-Group-ID LPAR CPU FL Status Sysplex Max_Cyls Time\n";
+printf "================================================================================\n";
+
+# mask bits for online and reserved state
+online_reserved_mask=0xE0
+
+# print name value lists
+for i in `seq 1 $count`;
+do
+ # get flags field
+ value=${status_flags[$i]}
+ # mark as hex value
+ value=0x$value
+ # mask online and reserved bits
+ value=$(($value & $online_reserved_mask))
+
+ case $value in
+ 0 ) # 0x00
+ STATE="OFF"
+ ;;
+ 32 ) # 0x20
+ STATE="OFF-RSV"
+ ;;
+ 64 ) # 0x40
+ STATE="ON"
+ ;;
+ 96 ) # 0x60
+ STATE="ON-RSV"
+ ;;
+ * )
+ STATE="-"
+ ;;
+ esac
+
+ printf "%22s %02s %07s %02s %-6s %-8s %11u %10lu\n" \
+ "${pgid[$i]}" \
+ "${pgid[$i]:4:2}" \
+ "${pgid[$i]:6:4}" \
+ "${status_flags[$i]}" \
+ "$STATE" \
+ "${sysplex_name[$i]}" \
+ "${supported_cylinder[$i]}" \
+ "${timestamp[$i]}" \
+ ;
+done
+printf "\n";
+
+rm -f $temp
+}
+
function uid()
{
#-------------------------------------------#
@@ -586,6 +715,9 @@ while [ $# -gt 0 ]; do
--long|-l)
OUTPUT="extended"
;;
+ --host-access-list|-H)
+ OUTPUT="host"
+ ;;
--version)
PrintVersion
exit 0
@@ -626,8 +758,13 @@ fi
# gather information on devices in list
PROCESSING=" $PROCESSING | gatherDeviceData "
+
# sort resulting list
-PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- "
+if [[ "$OUTPUT" == "host" ]]; then
+ PROCESSING=" $PROCESSING"
+else
+ PROCESSING=" $PROCESSING | sort -t: -k1n -k2 | cut -d: -f3- "
+fi
if [[ "$PRINTUID" == "true" ]] && [[ "$OUTPUT" != "old" ]]; then
printf "Bus-ID Name UID\n"
--- a/zconf/lsdasd.8
+++ b/zconf/lsdasd.8
@@ -40,11 +40,14 @@ Include only base devices.
Old output of lsdasd for compatibility.
.TP
.BR -l | --long
-Extended output of lsdasd including UID, attributes and path information.
+Extended output of lsdasd including UID and attributes.
.TP
.BR -u | --uid
Output includes and is sorted by UID.
.TP
+.BR -H | --host-acces
+Show information about all hosts using this device.
+.TP
.BR -v | --verbose
Only for compatibility (and maybe future) use. This option currently does
nothing.
--- a/zdsfs/zdsfs.1
+++ b/zdsfs/zdsfs.1
@@ -150,6 +150,10 @@ If \fI<s>\fR is set to 0, no seek histor
case `seek' is still supported, but a `seek' operation might result in a
read from the beginning of the data set.
+.TP
+\fB\-o\fR check_host_count
+Stop processing if the device is used by another operating system instance.
+
.SS "Applicable FUSE options (version 2.8):"
This is a selected subset of all FUSE options. Use the zdsfs
\fB\--help\fR option to print a full list.
--- a/zdsfs/zdsfs.c
+++ b/zdsfs/zdsfs.c
@@ -39,6 +39,7 @@ struct zdsfs_info {
int devcount;
int allow_inclomplete_multi_volume;
int keepRDW;
+ int host_count;
unsigned int tracks_per_frame;
unsigned long long seek_buffer_size;
struct zdsroot *zdsroot;
@@ -765,6 +766,7 @@ static const struct fuse_opt zdsfs_opts[
FUSE_OPT_KEY("seekbuffer=", KEY_SEEKBUFFER),
ZDSFS_OPT("rdw", keepRDW, 1),
ZDSFS_OPT("ignore_incomplete", allow_inclomplete_multi_volume, 1),
+ ZDSFS_OPT("check_host_count", host_count, 1),
FUSE_OPT_END
};
@@ -790,7 +792,10 @@ static void usage(const char *progname)
" data set are missing\n"
" -o tracks=N Size of the track buffer in tracks (default 128)\n"
" -o seekbuffer=S Upper limit in bytes for the seek history buffer\n"
-" size (default 1048576)\n", progname);
+" size (default 1048576)\n"
+" -o check_host_count Stop processing if the device is used by another\n"
+" operating system instance\n"
+ , progname);
}
static void zdsfs_process_device(const char *device)
@@ -1014,6 +1019,17 @@ int main(int argc, char *argv[])
argv[0]);
exit(1);
}
+
+ if (zdsfsinfo.host_count) {
+ /* check, print error and exit if multiple online */
+ rc = lzds_analyse_open_count(zdsfsinfo.zdsroot, 0);
+ if (rc == -EACCES)
+ goto cleanup;
+ } else {
+ /* check, print warning if multiple online */
+ lzds_analyse_open_count(zdsfsinfo.zdsroot, 1);
+ }
+
rc = zdsfs_verify_datasets();
if (rc)
goto cleanup;

View File

@ -0,0 +1,37 @@
Subject: [PATCH] [BZ 140500] libu2s: Fix busid parsing
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Description: libu2s: Fix busid parsing
Symptom: dasdview displays a wrong busid and shows the error message
"Error: dasdview: Could not retrieve raw_track_access mode
information.", which is wrong as well.
Problem: dasdview retrieves the busid information from libu2s. Whenever
an FBA DASD is listed prior to the target DASD in
/proc/dasd/devices, the parsing will fail due to an additional
whitespace character. For example, an entry for ECKD devices
starts with "0.0.5e30(ECKD)...", while an entry for FBA starts
with "0.0.8000(FBA )...".
Solution: Change the busid parsing in libu2s by explicitly looking for the
closing bracket.
Reproduction: Add an FBA device and then an ECKD device to the system and use
dasdview to display information about the ECKD device.
# dasdview -i /dev/dasdX
Upstream-ID: -
Problem-ID: 140500
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
libu2s/u2s.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/libu2s/u2s.c
+++ b/libu2s/u2s.c
@@ -237,7 +237,7 @@ static int find_busid_in_proc(int maja,
filp = fopen("/proc/dasd/devices", "r");
if (!filp)
return rc;
- while (fscanf(filp, "%[^(] %*s at ( %d : %d %*[^\n]\n",
+ while (fscanf(filp, "%[^(] %*[^)] ) at ( %d : %d %*[^\n]\n",
bus, &majb, &minb) != EOF) {
if ((maja == majb) && (mina == minb)) {
strncpy(busid, bus, BUSIDSIZE + 1);

View File

@ -0,0 +1,37 @@
Subject: lscss: allow to specify devices from ssid > 2
From: Sebastian Ott <sebott@linux.vnet.ibm.com>
Description: lscss: allow to specify devices from ssid > 2
Symptom: Specifying devices with ssid > 2 results in:
"Syntax error: 0.3.0000"
Problem: SSIDs > 2 are disallowed
Solution: allow SSIDs > 2
Reproduction: lscss 0.3.0000
Upstream-ID: -
Problem-ID: 150872
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
---
zconf/lscss | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/zconf/lscss
+++ b/zconf/lscss
@@ -61,7 +61,7 @@ SUBCHANNEL_TYPE_IO=0
SUBCHANNEL_TYPE_CHSC=1
SUBCHANNEL_TYPE_EADM=3
-IDFORMAT=[[:xdigit:]]*.[0-3].[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]
+IDFORMAT=[[:xdigit:]]*.[[:xdigit:]].[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]
unset SCH_IO SCH_CHSC SCH_EADM SHOW_AVAIL UPPERCASE SHORTID DEVTYPES DEVRANGE
unset RANGE SHOW_VPM
@@ -81,7 +81,7 @@ function check_id() #return 0 if $1 has
fi
;;
3)
- if [ ${#__ID[2]} != 4 -o ${#__ID[1]} != 1 -o "${__ID[1]//[012]/}" \
+ if [ ${#__ID[2]} != 4 -o ${#__ID[1]} != 1 \
-o \( ${#__ID[0]} != 2 -a ${#__ID[0]} != 1 \) ] ;then
return 1
fi

View File

@ -0,0 +1,35 @@
Subject: [PATCH] [BZ 143050] zipl/boot: fix failed start subchannel in FBA loader
From: Stefan Haberland <sth@linux.vnet.ibm.com>
Description: zipl/boot: fix failed start subchannel in FBA loader
Symptom: IPL of a FBA device fails with:
Start subchannel failed
disabled wait PSW 00020000 80000000 00000000 00004502
Problem: The FBA loader has only a limited amount of memory to build CCW
requests. Therefore larger I/O requests need to be split.
This splitting was off by one leading to the fact that one CCW
request uses memory of another data structure which in turn leads
to corrupted data.
Solution: Fix by correcting the split rule.
Reproduction: IPL a FBA device.
The error might occur randomly depending on the size of the
kernel image and offsets within it.
Upstream-ID: -
Problem-ID: 143050
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
---
zipl/boot/fba2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/zipl/boot/fba2.c
+++ b/zipl/boot/fba2.c
@@ -59,7 +59,7 @@ restart:
memset(irb, 0, sizeof(struct irb));
memset(&orb, 0, sizeof(struct orb));
- if (blockptr->blockct > MAX_BLOCKCT) {
+ if (blockptr->blockct >= MAX_BLOCKCT) {
record_number = MAX_BLOCKCT - 1;
blockptr->blockct -= MAX_BLOCKCT;
} else {

View File

@ -0,0 +1,42 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: 9e49066f5c779e6591b06d2276add744ea8ca4d0
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Fix behaviour of -t combined with -y
When -t (testmode) is being combined with -y (noprompt), the
informations about what dasdfmt *would* do, is not being displayed.
Simply fix this by checking whether testmode is set.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -894,7 +894,7 @@ static void do_format_dasd(dasdfmt_info_
vtoc_volume_label_set_label(vlabel, "LNX1");
}
- if ((info->verbosity > 0) || (!info->withoutprompt))
+ if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
dasdfmt_print_info(info, vlabel, cylinders, heads, p);
count = u2s_get_host_access_count(info->devname);

View File

@ -0,0 +1,250 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Fix trailing whitespace
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 58 +++++++++++++++++++++++++++---------------------------
1 file changed, 29 insertions(+), 29 deletions(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -133,7 +133,7 @@ static void program_interrupt_signal (in
rc = close(filedes);
if (rc)
- ERRMSG("%s: (signal handler) Unable to close device (%s)\n",
+ ERRMSG("%s: (signal handler) Unable to close device (%s)\n",
prog_name, strerror(errno));
signal (sig, SIG_DFL);
@@ -329,7 +329,7 @@ retry:
/*
- * check the volume serial for special
+ * check the volume serial for special
* characters and move blanks to the end
*/
static int check_volser(char *s, int devno)
@@ -345,7 +345,7 @@ static int check_volser(char *s, int dev
s[i] = ' ';
s[i] = toupper(s[i]);
}
- s[6] = 0x00;
+ s[6] = 0x00;
for (i=0; i<6; i++) {
if (s[i] == ' ')
@@ -416,16 +416,16 @@ static format_data_t ask_user_for_blksiz
break;
rc = sscanf(buffer,"%d%c", &params.blksize, &c);
- if ((rc == 2) && (c == '\n'))
+ if ((rc == 2) && (c == '\n'))
rc = 1;
- if (rc == -1)
+ if (rc == -1)
rc = 1; /* this happens, if enter is pressed */
- if (rc != 1)
+ if (rc != 1)
printf(" -- wrong input, try again.\n");
if (check_param(str, ERR_LENGTH, &params) < 0) {
- printf(" -- %s\n",str);
- rc = 0;
+ printf(" -- %s\n",str);
+ rc = 0;
}
} while (rc != 1);
@@ -479,7 +479,7 @@ static int dasdfmt_get_volser(char * dev
volume_label_t vlabel;
if ((f = open(devname, O_RDONLY)) == -1)
- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
+ ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
prog_name, devname, strerror(errno));
if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
@@ -491,7 +491,7 @@ static int dasdfmt_get_volser(char * dev
"failed (%s).\n", prog_name, strerror(errno));
if (close(f) != 0)
- ERRMSG("%s: error during close: %s\ncontinuing...\n",
+ ERRMSG("%s: error during close: %s\ncontinuing...\n",
prog_name, strerror(errno));
if ((strncmp(dasd_info.type, "ECKD", 4) == 0) &&
@@ -505,7 +505,7 @@ static int dasdfmt_get_volser(char * dev
return -1;
}
}
-
+
/*
* do all the labeling (volume label and initial VTOC)
*/
@@ -577,7 +577,7 @@ static void dasdfmt_write_labels(dasdfmt
rc = lseek(filedes, label_position, SEEK_SET);
if (rc != label_position)
ERRMSG_EXIT(EXIT_FAILURE, "%s: lseek command to %i failed "
- "(%s).\n", prog_name, label_position,
+ "(%s).\n", prog_name, label_position,
strerror(errno));
rc = write(filedes, ipl2_record, ipl2_record_len);
@@ -633,9 +633,9 @@ static void dasdfmt_write_labels(dasdfmt
rc = lseek(filedes, label_position, SEEK_SET);
if (rc != label_position)
ERRMSG_EXIT(EXIT_FAILURE, "%s: lseek command to %i failed "
- "(%s).\n", prog_name, label_position,
+ "(%s).\n", prog_name, label_position,
strerror(errno));
-
+
/* write VTOC FMT4 DSCB */
rc = write(filedes, &f4, sizeof(format4_label_t));
if (rc != sizeof(format4_label_t))
@@ -695,21 +695,21 @@ static void dasdfmt_format(dasdfmt_info_
"using the default.\n");
info->hashstep = 10;
}
-
+
if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n",
info->hashstep);
}
format_step.blksize = format_params->blksize;
format_step.intensity = format_params->intensity;
-
+
k = 0;
cyl = 1;
if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
printf("\n");
while (1) {
- p1 = -1;
+ p1 = -1;
p2 = 0;
if (k + heads * reqsize >= format_params->stop_unit)
reqsize = 1;
@@ -734,7 +734,7 @@ static void dasdfmt_format(dasdfmt_info_
tmp = cyl*50/cylinders;
for (j=1; j<=tmp; j++)
printf("#");
- for (j=tmp+1; j<=50; j++)
+ for (j=tmp+1; j<=50; j++)
printf("-");
printf("|%3d%%", p1);
}
@@ -758,15 +758,15 @@ static void dasdfmt_format(dasdfmt_info_
k += reqsize * heads;
cyl += reqsize;
}
- else
+ else
k += format_params->stop_unit % heads;
- if (k > format_params->stop_unit)
+ if (k > format_params->stop_unit)
break;
}
if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
- printf("\n\n");
+ printf("\n\n");
}
@@ -790,7 +790,7 @@ static void dasdfmt_prepare_and_format (
if (ioctl(filedes, BIODASDDISABLE, p) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
- "BIODASDDISABLE failed. (%s)\n", prog_name,
+ "BIODASDDISABLE failed. (%s)\n", prog_name,
strerror(errno));
disk_disabled = 1;
@@ -798,7 +798,7 @@ static void dasdfmt_prepare_and_format (
if (ioctl(filedes, BIODASDFMT, &temp) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (invalidate first track) IOCTL "
- "BIODASDFMT failed. (%s)\n", prog_name,
+ "BIODASDFMT failed. (%s)\n", prog_name,
strerror(errno));
/* except track 0 from standard formatting procss */
@@ -814,14 +814,14 @@ static void dasdfmt_prepare_and_format (
if (ioctl(filedes, BIODASDFMT, &temp) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (re-validate first track) IOCTL"
- " BIODASDFMT failed (%s)\n", prog_name,
+ " BIODASDFMT failed (%s)\n", prog_name,
strerror(errno));
if (info->verbosity > 0) printf("Re-accessing the device...\n");
if (ioctl(filedes, BIODASDENABLE, p) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
- "BIODASDENABLE failed. (%s)\n", prog_name,
+ "BIODASDENABLE failed. (%s)\n", prog_name,
strerror(errno));
disk_disabled = 0;
}
@@ -830,7 +830,7 @@ static void dasdfmt_prepare_and_format (
/*
*
*/
-static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
+static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
volume_label_t *vlabel)
{
char inp_buffer[5];
@@ -943,7 +943,7 @@ static void do_format_dasd(dasdfmt_info_
if (!info->yast_mode)
printf("Finished formatting the device.\n");
- if (!info->writenolabel)
+ if (!info->writenolabel)
dasdfmt_write_labels(info, vlabel, cylinders, heads);
if (!info->yast_mode)
@@ -959,7 +959,7 @@ static void do_format_dasd(dasdfmt_info_
}
-int main(int argc,char *argv[])
+int main(int argc,char *argv[])
{
dasdfmt_info_t info;
volume_label_t vlabel;
@@ -1001,7 +1001,7 @@ int main(int argc,char *argv[])
rc=getopt_long(argc, argv, dasdfmt_getopt_string,
dasdfmt_getopt_long_options, &index);
- switch (rc)
+ switch (rc)
{
case 'F':
info.force=1;

View File

@ -0,0 +1,892 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Apply coding convention
Improve the overall readability of the code by applying the Kernel
coding convention.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 362 +++++++++++++++++++++++++-----------------------------
1 file changed, 171 insertions(+), 191 deletions(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -37,11 +37,10 @@ int reqsize;
/*
* Print version information.
*/
-static void
-print_version (void)
+static void print_version(void)
{
- printf ("%s version %s\n", tool_name, RELEASE_STRING);
- printf ("%s\n", copyright_notice);
+ printf("%s version %s\n", tool_name, RELEASE_STRING);
+ printf("%s\n", copyright_notice);
}
/*
@@ -54,7 +53,7 @@ static void exit_usage(int exitcode)
" [-b <blocksize> | --blocksize=<blocksize>]\n"
" [-d <disk layout> | --disk_layout=<disk layout>]\n"
" [-r <cylinder> | --requestsize=<cylinder>]\n"
- " <device>\n\n",prog_name);
+ " <device>\n\n", prog_name);
printf(" -t or --test means testmode\n"
" -V or --version means print version\n"
@@ -71,13 +70,13 @@ static void exit_usage(int exitcode)
" -C or --check_host_count means force dasdfmt to check\n"
" the host access open count to ensure the device\n"
" is not online on another operating system instance\n"
- " --norecordzero prevent storage server from modifying"
- " record 0\n\n"
+ " --norecordzero prevent storage server from modifying"
+ " record 0\n\n"
" <volser> is the volume identifier, which is converted\n"
- " to EBCDIC and written to disk. \n"
+ " to EBCDIC and written to disk.\n"
" (6 characters, e.g. LNX001\n"
" <blocksize> has to be power of 2 and at least 512\n"
- " <disk layout> is either \n"
+ " <disk layout> is either\n"
" 'cdl' for compatible disk layout (default) or\n"
" 'ldl' for linux disk layout\n"
" <device> device node of the device to format\n");
@@ -106,38 +105,39 @@ static int reread_partition_table(void)
* signal handler:
* enables the disk again in case of SIGTERM, SIGINT and SIGQUIT
*/
-static void program_interrupt_signal (int sig)
+static void program_interrupt_signal(int sig)
{
int rc;
if (program_interrupt_in_progress)
- raise (sig);
+ raise(sig);
program_interrupt_in_progress = 1;
if (disk_disabled) {
- printf("Re-accessing the device... \n");
+ printf("Re-accessing the device...\n");
rc = ioctl(filedes, BIODASDENABLE, &format_params);
if (rc)
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: (signal handler) IOCTL BIODASDENABLE "
- "failed (%s)\n",prog_name,strerror(errno));
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (signal handler) IOCTL "
+ "BIODASDENABLE failed (%s)\n", prog_name,
+ strerror(errno));
}
- printf("Rereading the partition table... \n");
+ printf("Rereading the partition table...\n");
rc = reread_partition_table();
if (rc) {
ERRMSG("%s: (signal handler) Re-reading partition table "
"failed. (%s)\n", prog_name, strerror(errno));
- } else
+ } else {
printf("Exiting...\n");
+ }
rc = close(filedes);
if (rc)
ERRMSG("%s: (signal handler) Unable to close device (%s)\n",
prog_name, strerror(errno));
- signal (sig, SIG_DFL);
- raise (sig);
+ signal(sig, SIG_DFL);
+ raise(sig);
}
@@ -171,13 +171,13 @@ static void get_device_name(dasdfmt_info
char* device;
int i;
- if ((strchr(name, ' ') != NULL)||(strchr(name, '#') != NULL)||
- (strchr(name, '[') != NULL)||(strchr(name, ']') != NULL)||
- (strchr(name, '!') != NULL)||(strchr(name, '>') != NULL)||
- (strchr(name, '(') != NULL)||(strchr(name, '<') != NULL)||
- (strchr(name, ')') != NULL)||(strchr(name, ':') != NULL)||
- (strchr(name, '&') != NULL)||(strchr(name, ';') != NULL))
- ERRMSG_EXIT(EXIT_MISUSE,"%s: Your filename contains "
+ if ((strchr(name, ' ') != NULL) || (strchr(name, '#') != NULL) ||
+ (strchr(name, '[') != NULL) || (strchr(name, ']') != NULL) ||
+ (strchr(name, '!') != NULL) || (strchr(name, '>') != NULL) ||
+ (strchr(name, '(') != NULL) || (strchr(name, '<') != NULL) ||
+ (strchr(name, ')') != NULL) || (strchr(name, ':') != NULL) ||
+ (strchr(name, '&') != NULL) || (strchr(name, ';') != NULL))
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Your filename contains "
"blanks or special characters!\n",
prog_name);
@@ -215,14 +215,14 @@ static void get_device_name(dasdfmt_info
info->devname[PATH_MAX - 1] = '\0';
if (stat(info->devname, &dev_stat) != 0)
- ERRMSG_EXIT(EXIT_MISUSE,
- "%s: Could not get information for device node %s: %s\n",
- prog_name, info->devname, strerror(errno));
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Could not get information for "
+ "device node %s: %s\n", prog_name, info->devname,
+ strerror(errno));
if (minor(dev_stat.st_rdev) & PARTN_MASK) {
- ERRMSG_EXIT(EXIT_MISUSE,
- "%s: Unable to format partition %s. Please specify a device.\n",
- prog_name, info->devname);
+ ERRMSG_EXIT(EXIT_MISUSE, "%s: Unable to format partition %s. "
+ "Please specify a device.\n", prog_name,
+ info->devname);
}
if (util_proc_dev_get_entry(dev_stat.st_rdev, 1, &dev_entry) == 0) {
@@ -253,7 +253,7 @@ static void init_info(dasdfmt_info_t *in
info->force = 0;
info->writenolabel = 0;
info->labelspec = 0;
- info->cdl_format = 0;
+ info->cdl_format = 0;
info->blksize_specified = 0;
info->reqsize_specified = 0;
info->node_specified = 0;
@@ -263,7 +263,6 @@ static void init_info(dasdfmt_info_t *in
info->yast_mode = 0;
}
-
/*
* check for disk type and set some variables (e.g. usage count)
*/
@@ -280,9 +279,9 @@ static void check_disk(dasdfmt_info_t *i
"status information failed (%s)\n",
prog_name, strerror(errno_save));
}
- if (ro) {
+ if (ro)
ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n");
- }
+
retry:
if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
errno_save = errno;
@@ -314,7 +313,7 @@ retry:
info->usage_count = dasd_info.open_count;
info->devno = dasd_info.devno;
- if (strncmp(dasd_info.type, "ECKD",4) != 0) {
+ if (strncmp(dasd_info.type, "ECKD", 4) != 0) {
ERRMSG_EXIT(EXIT_FAILURE,
"%s: Unsupported disk type\n%s is not an "
"ECKD disk!\n", prog_name, info->devname);
@@ -327,29 +326,28 @@ retry:
}
}
-
/*
* check the volume serial for special
* characters and move blanks to the end
*/
static int check_volser(char *s, int devno)
{
- int i,j;
+ int i, j;
- for (i=0; i<6; i++) {
+ for (i = 0; i < 6; i++) {
if ((s[i] < 0x20) || (s[i] > 0x7a) ||
- ((s[i] >= 0x21)&&(s[i] <= 0x22)) || /* !" */
- ((s[i] >= 0x26)&&(s[i] <= 0x2f)) || /* &'()*+,-./ */
- ((s[i] >= 0x3a)&&(s[i] <= 0x3f)) || /* :;<=>? */
- ((s[i] >= 0x5b)&&(s[i] <= 0x60))) /* \]^_` */
+ ((s[i] >= 0x21) && (s[i] <= 0x22)) || /* !" */
+ ((s[i] >= 0x26) && (s[i] <= 0x2f)) || /* &'()*+,-./ */
+ ((s[i] >= 0x3a) && (s[i] <= 0x3f)) || /* :;<=>? */
+ ((s[i] >= 0x5b) && (s[i] <= 0x60))) /* \]^_` */
s[i] = ' ';
s[i] = toupper(s[i]);
}
s[6] = 0x00;
- for (i=0; i<6; i++) {
+ for (i = 0; i < 6; i++) {
if (s[i] == ' ')
- for (j=i; j<6; j++)
+ for (j = i; j < 6; j++)
if (s[j] != ' ') {
s[i] = s[j];
s[j] = ' ';
@@ -360,7 +358,7 @@ static int check_volser(char *s, int dev
if (s[0] == ' ') {
printf("Usage error, switching to default.\n");
sprintf(s, "0X%04x", devno);
- for (i=0; i<6; i++)
+ for (i = 0; i < 6; i++)
s[i] = toupper(s[i]);
return -1;
}
@@ -368,7 +366,6 @@ static int check_volser(char *s, int dev
return 0;
}
-
/*
* do some blocksize checks
*/
@@ -377,7 +374,7 @@ static int check_param(char *s, size_t b
int tmp = data->blksize;
if ((tmp < 512) || (tmp > 4096)) {
- strncpy(s,"Blocksize must be one of the following positive "
+ strncpy(s, "Blocksize must be one of the following positive "
"integers:\n512, 1024, 2048, 4096.", buffsize);
if (buffsize > 0)
s[buffsize - 1] = '\0';
@@ -386,7 +383,7 @@ static int check_param(char *s, size_t b
while (tmp > 0) {
if ((tmp % 2) && (tmp != 1)) {
- strncpy(s,"Blocksize must be a power of 2.", buffsize);
+ strncpy(s, "Blocksize must be a power of 2.", buffsize);
if (buffsize > 0)
s[buffsize - 1] = '\0';
return -1;
@@ -397,7 +394,6 @@ static int check_param(char *s, size_t b
return 0;
}
-
/*
* ask the user to specify a blocksize
*/
@@ -415,7 +411,7 @@ static format_data_t ask_user_for_blksiz
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
break;
- rc = sscanf(buffer,"%d%c", &params.blksize, &c);
+ rc = sscanf(buffer, "%d%c", &params.blksize, &c);
if ((rc == 2) && (c == '\n'))
rc = 1;
if (rc == -1)
@@ -424,7 +420,7 @@ static format_data_t ask_user_for_blksiz
printf(" -- wrong input, try again.\n");
if (check_param(str, ERR_LENGTH, &params) < 0) {
- printf(" -- %s\n",str);
+ printf(" -- %s\n", str);
rc = 0;
}
} while (rc != 1);
@@ -432,7 +428,6 @@ static format_data_t ask_user_for_blksiz
return params;
}
-
/*
* print all information needed to format the device
*/
@@ -449,7 +444,7 @@ static void dasdfmt_print_info(dasdfmt_i
printf("%s in the following way:\n", info->devname);
printf(" Device number of device : 0x%x\n", info->devno);
printf(" Labelling device : %s\n",
- (info->writenolabel)?"no":"yes");
+ (info->writenolabel) ? "no" : "yes");
if (!info->writenolabel) {
vtoc_volume_label_get_label(vlabel, vollbl);
@@ -460,31 +455,31 @@ static void dasdfmt_print_info(dasdfmt_i
printf(" Extent start (trk no) : %u\n", p->start_unit);
printf(" Extent end (trk no) : %u\n", p->stop_unit);
printf(" Compatible Disk Layout : %s\n",
- (p->intensity & DASD_FMT_INT_COMPAT)?"yes":"no");
+ (p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
printf(" Blocksize : %d\n", p->blksize);
if (info->testmode)
printf("Test mode active, omitting ioctl.\n");
}
-
/*
* get volser
*/
-static int dasdfmt_get_volser(char * devname, char * volser)
+static int dasdfmt_get_volser(char *devname, char *volser)
{
- dasd_information_t dasd_info;
+ dasd_information_t dasd_info;
int blksize;
int f;
volume_label_t vlabel;
- if ((f = open(devname, O_RDONLY)) == -1)
- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
+ f = open(devname, O_RDONLY);
+ if (f == -1)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
prog_name, devname, strerror(errno));
if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD"
- "INFO failed (%s).\n",prog_name, strerror(errno));
+ "INFO failed (%s).\n", prog_name, strerror(errno));
if (ioctl(f, BLKSSZGET, &blksize) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
@@ -500,8 +495,7 @@ static int dasdfmt_get_volser(char * dev
vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel);
vtoc_volume_label_get_volser(&vlabel, volser);
return 0;
- }
- else {
+ } else {
return -1;
}
}
@@ -512,22 +506,24 @@ static int dasdfmt_get_volser(char * dev
static void dasdfmt_write_labels(dasdfmt_info_t *info, volume_label_t *vlabel,
unsigned int cylinders, unsigned int heads)
{
- int label_position;
- dasd_information_t dasd_info;
- struct hd_geometry geo;
- format4_label_t f4;
- format5_label_t f5;
- format7_label_t f7;
+ int label_position;
+ dasd_information_t dasd_info;
+ struct hd_geometry geo;
+ format4_label_t f4;
+ format5_label_t f5;
+ format7_label_t f7;
int rc, blksize;
void *ipl1_record, *ipl2_record;
int ipl1_record_len, ipl2_record_len;
- if (info->verbosity > 0) printf("Retrieving dasd information... ");
+ if (info->verbosity > 0)
+ printf("Retrieving dasd information... ");
if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BIODASD"
- "INFO failed (%s).\n",prog_name, strerror(errno));
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL "
+ "BIODASDINFO failed (%s).\n",
+ prog_name, strerror(errno));
if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET "
@@ -539,13 +535,16 @@ static void dasdfmt_write_labels(dasdfmt
* vary depending on the format.
*/
if (ioctl(filedes, HDIO_GETGEO, &geo) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL HDIO_GET"
- "GEO failed (%s).\n", prog_name, strerror(errno));
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL "
+ "HDIO_GETGEO failed (%s).\n",
+ prog_name, strerror(errno));
- if (info->verbosity > 0) printf("ok\n");
+ if (info->verbosity > 0)
+ printf("ok\n");
/* write empty bootstrap (initial IPL records) */
- if (info->verbosity > 0) printf("Writing empty bootstrap...\n");
+ if (info->verbosity > 0)
+ printf("Writing empty bootstrap...\n");
/*
* Note: ldl labels do not contain the key field
@@ -596,7 +595,8 @@ static void dasdfmt_write_labels(dasdfmt
label_position = dasd_info.label_block * blksize;
- if (info->verbosity > 0) printf("Writing label...\n");
+ if (info->verbosity > 0)
+ printf("Writing label...\n");
rc = lseek(filedes, label_position, SEEK_SET);
if (rc != label_position)
@@ -608,10 +608,10 @@ static void dasdfmt_write_labels(dasdfmt
* Note: cdl volume labels do not contain the 'formatted_blocks' part
* and ldl labels do not contain the key field
*/
- if (info->cdl_format)
+ if (info->cdl_format) {
rc = write(filedes, vlabel, (sizeof(*vlabel) -
sizeof(vlabel->formatted_blocks)));
- else {
+ } else {
vlabel->ldl_version = 0xf2; /* EBCDIC '2' */
vlabel->formatted_blocks = cylinders * heads * geo.sectors;
rc = write(filedes, &vlabel->vollbl, (sizeof(*vlabel)
@@ -625,7 +625,8 @@ static void dasdfmt_write_labels(dasdfmt
ERRMSG_EXIT(EXIT_FAILURE, "%s: Error writing volume label "
"(%d).\n", prog_name, rc);
- if (info->verbosity > 0) printf("Writing VTOC... ");
+ if (info->verbosity > 0)
+ printf("Writing VTOC... ");
label_position = (VTOC_START_CC * heads + VTOC_START_HH) *
geo.sectors * blksize;
@@ -673,10 +674,10 @@ static void dasdfmt_write_labels(dasdfmt
fsync(filedes);
- if (info->verbosity > 0) printf("ok\n");
+ if (info->verbosity > 0)
+ printf("ok\n");
}
-
/*
* formats the disk cylinderwise
*/
@@ -720,21 +721,20 @@ static void dasdfmt_format(dasdfmt_info_
format_step.start_unit += 1;
if (ioctl(filedes, BIODASDFMT, &format_step) != 0)
- ERRMSG_EXIT(EXIT_FAILURE,"%s: (format cylinder) IOCTL "
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL "
"BIODASDFMT failed. (%s)\n",
prog_name, strerror(errno));
if (info->print_progressbar) {
printf("cyl %7d of %7d |", cyl, cylinders);
p2 = p1;
- p1 = cyl*100/cylinders;
- if (p1 != p2)
- {
+ p1 = cyl * 100 / cylinders;
+ if (p1 != p2) {
/* percent value has changed */
- tmp = cyl*50/cylinders;
- for (j=1; j<=tmp; j++)
+ tmp = cyl * 50 / cylinders;
+ for (j = 1; j <= tmp; j++)
printf("#");
- for (j=tmp+1; j<=50; j++)
+ for (j = tmp + 1; j <= 50; j++)
printf("-");
printf("|%3d%%", p1);
}
@@ -748,6 +748,7 @@ static void dasdfmt_format(dasdfmt_info_
fflush(stdout);
hashcount++;
}
+
if (info->print_percentage) {
printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders,
cyl*100/cylinders);
@@ -757,9 +758,9 @@ static void dasdfmt_format(dasdfmt_info_
if (k % heads == 0) {
k += reqsize * heads;
cyl += reqsize;
- }
- else
+ } else {
k += format_params->stop_unit % heads;
+ }
if (k > format_params->stop_unit)
break;
@@ -769,14 +770,9 @@ static void dasdfmt_format(dasdfmt_info_
printf("\n\n");
}
-
-/*
- *
- */
-static void dasdfmt_prepare_and_format (dasdfmt_info_t *info,
- unsigned int cylinders,
- unsigned int heads,
- format_data_t *p)
+static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
+ unsigned int cylinders,
+ unsigned int heads, format_data_t *p)
{
format_data_t temp = {
start_unit: 0,
@@ -786,7 +782,8 @@ static void dasdfmt_prepare_and_format (
| DASD_FMT_INT_INVAL)
};
- if (info->verbosity > 0) printf("Detaching the device...\n");
+ if (info->verbosity > 0)
+ printf("Detaching the device...\n");
if (ioctl(filedes, BIODASDDISABLE, p) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
@@ -794,7 +791,8 @@ static void dasdfmt_prepare_and_format (
strerror(errno));
disk_disabled = 1;
- if (info->verbosity > 0) printf("Invalidate first track...\n");
+ if (info->verbosity > 0)
+ printf("Invalidate first track...\n");
if (ioctl(filedes, BIODASDFMT, &temp) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (invalidate first track) IOCTL "
@@ -806,18 +804,21 @@ static void dasdfmt_prepare_and_format (
dasdfmt_format(info, cylinders, heads, p);
- if (info->verbosity > 0) printf("formatting tracks complete...\n");
+ if (info->verbosity > 0)
+ printf("formatting tracks complete...\n");
temp.intensity = p->intensity;
- if (info->verbosity > 0) printf("Revalidate first track...\n");
+ if (info->verbosity > 0)
+ printf("Revalidate first track...\n");
if (ioctl(filedes, BIODASDFMT, &temp) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (re-validate first track) IOCTL"
" BIODASDFMT failed (%s)\n", prog_name,
strerror(errno));
- if (info->verbosity > 0) printf("Re-accessing the device...\n");
+ if (info->verbosity > 0)
+ printf("Re-accessing the device...\n");
if (ioctl(filedes, BIODASDENABLE, p) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
@@ -826,20 +827,17 @@ static void dasdfmt_prepare_and_format (
disk_disabled = 0;
}
-
-/*
- *
- */
static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
volume_label_t *vlabel)
{
- char inp_buffer[5];
+ char inp_buffer[5];
dasd_information_t dasd_info;
struct dasd_eckd_characteristics *characteristics;
unsigned int cylinders, heads;
int count;
- if (info->verbosity > 0) printf("Retrieving disk geometry...\n");
+ if (info->verbosity > 0)
+ printf("Retrieving disk geometry...\n");
if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) "
@@ -877,22 +875,23 @@ static void do_format_dasd(dasdfmt_info_
}
}
} else {
- if (!info->labelspec && !info->keep_volser) {
+ if (!info->labelspec && !info->keep_volser) {
char buf[7];
- sprintf(buf, "0X%04x", info->devno);
+ sprintf(buf, "0X%04x", info->devno);
check_volser(buf, info->devno);
vtoc_volume_label_set_volser(vlabel, buf);
}
- if (p->intensity & DASD_FMT_INT_COMPAT) {
+ if (p->intensity & DASD_FMT_INT_COMPAT) {
info->cdl_format = 1;
vtoc_volume_label_set_label(vlabel, "VOL1");
vtoc_volume_label_set_key(vlabel, "VOL1");
vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01);
- } else
+ } else {
vtoc_volume_label_set_label(vlabel, "LNX1");
- }
+ }
+ }
if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
dasdfmt_print_info(info, vlabel, cylinders, heads, p);
@@ -926,15 +925,15 @@ static void do_format_dasd(dasdfmt_info_
"untouched: ");
if (fgets(inp_buffer, sizeof(inp_buffer), stdin) == NULL)
return;
- if (strcasecmp(inp_buffer,"yes") &&
- strcasecmp(inp_buffer,"yes\n")) {
+ if (strcasecmp(inp_buffer, "yes") &&
+ strcasecmp(inp_buffer, "yes\n")) {
printf("Omitting ioctl call (disk will "
"NOT be formatted).\n");
return;
}
}
- if (!((info->withoutprompt)&&(info->verbosity<1)))
+ if (!((info->withoutprompt) && (info->verbosity < 1)))
printf("Formatting the device. This may take a "
"while (get yourself a coffee).\n");
@@ -954,12 +953,11 @@ static void do_format_dasd(dasdfmt_info_
} else {
if (!info->yast_mode)
printf("ok\n");
- }
+ }
}
}
-
-int main(int argc,char *argv[])
+int main(int argc, char *argv[])
{
dasdfmt_info_t info;
volume_label_t vlabel;
@@ -980,9 +978,9 @@ int main(int argc,char *argv[])
int running=0;
/* Establish a handler for interrupt signals. */
- signal (SIGTERM, program_interrupt_signal);
- signal (SIGINT, program_interrupt_signal);
- signal (SIGQUIT, program_interrupt_signal);
+ signal(SIGTERM, program_interrupt_signal);
+ signal(SIGINT, program_interrupt_signal);
+ signal(SIGQUIT, program_interrupt_signal);
/******************* initialization ********************/
prog_name = argv[0];
@@ -996,102 +994,81 @@ int main(int argc,char *argv[])
/*************** parse parameters **********************/
- while (1)
- {
- rc=getopt_long(argc, argv, dasdfmt_getopt_string,
- dasdfmt_getopt_long_options, &index);
+ while (1) {
+ rc = getopt_long(argc, argv, dasdfmt_getopt_string,
+ dasdfmt_getopt_long_options, &index);
- switch (rc)
- {
+ switch (rc) {
case 'F':
- info.force=1;
+ info.force = 1;
break;
-
- case 'd' :
- if (strncmp(optarg,"cdl",3)==0)
- {
+ case 'd':
+ if (strncmp(optarg, "cdl", 3) == 0) {
format_params.intensity |= DASD_FMT_INT_COMPAT;
- if (info.writenolabel)
- {
- printf("WARNING: using the cdl " \
- "format without writing a " \
- "label doesn't make much " \
+ if (info.writenolabel) {
+ printf("WARNING: using the cdl "
+ "format without writing a "
+ "label doesn't make much "
"sense!\n");
exit(1);
}
- }
- else if (strncmp(optarg,"ldl",3)==0)
+ } else if (strncmp(optarg, "ldl", 3) == 0) {
format_params.intensity &= ~DASD_FMT_INT_COMPAT;
- else
- {
+ } else {
printf("%s is not a valid option!\n", optarg);
exit(1);
}
- break;
-
+ break;
case 'y':
- info.withoutprompt=1;
+ info.withoutprompt = 1;
break;
-
case 'z':
- format_params.intensity |= DASD_FMT_INT_FMT_NOR0;
+ format_params.intensity |= DASD_FMT_INT_FMT_NOR0;
break;
-
case 't':
- info.testmode=1;
+ info.testmode = 1;
break;
-
case 'p':
if (!(info.print_hashmarks || info.print_percentage))
info.print_progressbar = 1;
break;
-
case 'm':
- if (!(info.print_progressbar || info.print_percentage))
- {
- hashstep_str=optarg;
- info.print_hashmarks=1;
+ if (!(info.print_progressbar || info.print_percentage)) {
+ hashstep_str = optarg;
+ info.print_hashmarks = 1;
}
break;
-
case 'Q':
if (!(info.print_hashmarks || info.print_progressbar))
info.print_percentage = 1;
break;
-
case 'v':
- info.verbosity=1;
+ info.verbosity = 1;
break;
-
case 'h':
exit_usage(0);
-
case 'V':
print_version();
exit(0);
-
case 'l':
- strncpy(buf, optarg, 6);
+ strncpy(buf, optarg, 6);
if (check_volser(buf, 0) < 0)
break;
- vtoc_volume_label_set_volser(&vlabel,buf);
- info.labelspec=1;
+ vtoc_volume_label_set_volser(&vlabel, buf);
+ info.labelspec = 1;
break;
-
case 'L':
- if (format_params.intensity & DASD_FMT_INT_COMPAT)
- {
- printf("WARNING: using the cdl format " \
- "without writing a label doesn't " \
+ if (format_params.intensity & DASD_FMT_INT_COMPAT) {
+ printf("WARNING: using the cdl format "
+ "without writing a label doesn't "
"make much sense!\n");
exit(1);
}
- info.writenolabel=1;
+ info.writenolabel = 1;
break;
-
- case 'b' :
- blksize_param_str=optarg;
- info.blksize_specified=1;
+ case 'b':
+ blksize_param_str = optarg;
+ info.blksize_specified = 1;
break;
case 'r':
reqsize_param_str = optarg;
@@ -1102,7 +1079,7 @@ int main(int argc,char *argv[])
ERRMSG_EXIT(EXIT_MISUSE,"%s: too many devices specified.\n",
prog_name);
dev_filename[dev_count++]=strdup(optarg);
- info.node_specified=1;
+ info.node_specified = 1;
break;
case 'Y' : /* YaST mode */
info.yast_mode=1;
@@ -1110,8 +1087,8 @@ int main(int argc,char *argv[])
case 'P' : /* max parallel formatting processes */
max_parallel=atoi(optarg);
break;
- case 'k' :
- info.keep_volser=1;
+ case 'k':
+ info.keep_volser = 1;
break;
case 'C':
info.force_host = 1;
@@ -1121,11 +1098,12 @@ int main(int argc,char *argv[])
info.device_id = optind;
break;
default:
- ERRMSG_EXIT(EXIT_MISUSE,
- "Try '%s --help' for more"
- " information.\n",prog_name);
+ ERRMSG_EXIT(EXIT_MISUSE, "Try '%s --help' for more"
+ " information.\n", prog_name);
}
- if (rc==-1) break; // exit loop if finished
+
+ if (rc == -1)
+ break; /* exit loop if finished */
}
CHECK_SPEC_MAX_ONCE(info.blksize_specified, "blocksize");
@@ -1222,7 +1200,7 @@ int main(int argc,char *argv[])
} else
reqsize = DEFAULT_REQUESTSIZE;
if (info.print_hashmarks)
- PARSE_PARAM_INTO(info.hashstep, hashstep_str,10,"hashstep");
+ PARSE_PARAM_INTO(info.hashstep, hashstep_str, 10, "hashstep");
get_device_name(&info, dev_filename[i]);
@@ -1230,22 +1208,24 @@ int main(int argc,char *argv[])
format_params = ask_user_for_blksize(format_params);
if (info.keep_volser) {
- if(format_params.intensity == 0x00) {
- printf("WARNING: VOLSER cannot be kept " \
+ if (format_params.intensity == 0x00) {
+ printf("WARNING: VOLSER cannot be kept "
"when using the ldl format!\n");
exit(1);
}
- if(dasdfmt_get_volser(info.devname, old_volser) == 0)
+ if (dasdfmt_get_volser(info.devname, old_volser) == 0)
vtoc_volume_label_set_volser(&vlabel, old_volser);
else
- ERRMSG_EXIT(EXIT_FAILURE,"%s: VOLSER not found on device %s\n",
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "%s: VOLSER not found on device %s\n",
prog_name, info.devname);
}
- if ((filedes = open(info.devname, O_RDWR)) == -1)
- ERRMSG_EXIT(EXIT_FAILURE,"%s: Unable to open device %s: %s\n",
+ filedes = open(info.devname, O_RDWR);
+ if (filedes == -1)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
prog_name, info.devname, strerror(errno));
check_disk(&info);

View File

@ -0,0 +1,399 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Use enhanced DASD information
Currently dasdfmt uses BIODASDINFO as the IOCTL command to retrieve
information about a DASD and stores them in dasd_information_t.
However, BIODASDINFO2 offers a few more useful information (which are
then stored in dasd_information2_t).
- Replace dasd_information_t with dasd_information2_t.
- Make the corresponding variable part of dasdfmt_info_t, since it is
used in several functions anyway and we can save a few parameters and
IOCTL calls.
- Change the initialization of dasdfmt_info_t. A separate function isn't
necessary for that.
- Put the BIODASDINFO2 IOCTL call in a separate function which is then
called only once.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 132 ++++++++++++++++++------------------------------------
dasdfmt/dasdfmt.h | 21 ++++++--
2 files changed, 61 insertions(+), 92 deletions(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -237,30 +237,18 @@ static void get_device_name(dasdfmt_info
}
/*
- * initialize the dasdfmt info structure
+ * Retrieve DASD information
*/
-static void init_info(dasdfmt_info_t *info)
+static void get_device_info(dasdfmt_info_t *info)
{
- info->devno = 0x0;
- info->usage_count = 0;
- info->testmode = 0;
- info->verbosity = 0;
- info->withoutprompt = 0;
- info->print_progressbar = 0;
- info->print_hashmarks = 0;
- info->print_percentage = 0;
- info->hashstep = 0;
- info->force = 0;
- info->writenolabel = 0;
- info->labelspec = 0;
- info->cdl_format = 0;
- info->blksize_specified = 0;
- info->reqsize_specified = 0;
- info->node_specified = 0;
- info->device_id = 0;
- info->keep_volser = 0;
- info->force_host = 0;
- info->yast_mode = 0;
+ dasd_information2_t dasd_info;
+
+ if (ioctl(filedes, BIODASDINFO2, &dasd_info))
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call to retrieve "
+ "device information failed (%s).\n",
+ prog_name, strerror(errno));
+
+ info->dasd_info = dasd_info;
}
/*
@@ -268,7 +256,6 @@ static void init_info(dasdfmt_info_t *in
*/
static void check_disk(dasdfmt_info_t *info)
{
- dasd_information_t dasd_info;
int ro, errno_save, i = 0;
if (ioctl(filedes, BLKROGET, &ro) != 0) {
@@ -283,15 +270,6 @@ static void check_disk(dasdfmt_info_t *i
ERRMSG_EXIT(EXIT_FAILURE, "Disk is read only!\n");
retry:
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
- errno_save = errno;
- close(filedes);
- ERRMSG_EXIT(EXIT_FAILURE,
- "%s: the ioctl call to retrieve device "
- "information failed (%s)\n",
- prog_name, strerror(errno_save));
- }
-
if (!info->force)
/*
* udev strikes again.
@@ -302,7 +280,7 @@ retry:
* And confusing the hell out ouf anyone else.
* Bah.
*/
- if (dasd_info.open_count > 1) {
+ if (info->dasd_info.open_count > 1) {
if (i < 5) {
++i;
sleep(1);
@@ -311,9 +289,7 @@ retry:
ERRMSG_EXIT(EXIT_BUSY, "Disk in use!\n");
}
- info->usage_count = dasd_info.open_count;
- info->devno = dasd_info.devno;
- if (strncmp(dasd_info.type, "ECKD", 4) != 0) {
+ if (strncmp(info->dasd_info.type, "ECKD", 4) != 0) {
ERRMSG_EXIT(EXIT_FAILURE,
"%s: Unsupported disk type\n%s is not an "
"ECKD disk!\n", prog_name, info->devname);
@@ -442,7 +418,7 @@ static void dasdfmt_print_info(dasdfmt_i
printf("\nI am going to format the device ");
printf("%s in the following way:\n", info->devname);
- printf(" Device number of device : 0x%x\n", info->devno);
+ printf(" Device number of device : 0x%x\n", info->dasd_info.devno);
printf(" Labelling device : %s\n",
(info->writenolabel) ? "no" : "yes");
@@ -465,21 +441,16 @@ static void dasdfmt_print_info(dasdfmt_i
/*
* get volser
*/
-static int dasdfmt_get_volser(char *devname, char *volser)
+static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser)
{
- dasd_information_t dasd_info;
int blksize;
int f;
volume_label_t vlabel;
- f = open(devname, O_RDONLY);
+ f = open(info->devname, O_RDONLY);
if (f == -1)
ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
- prog_name, devname, strerror(errno));
-
- if (ioctl(f, BIODASDINFO, &dasd_info) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BIODASD"
- "INFO failed (%s).\n", prog_name, strerror(errno));
+ prog_name, info->devname, strerror(errno));
if (ioctl(f, BLKSSZGET, &blksize) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
@@ -489,10 +460,12 @@ static int dasdfmt_get_volser(char *devn
ERRMSG("%s: error during close: %s\ncontinuing...\n",
prog_name, strerror(errno));
- if ((strncmp(dasd_info.type, "ECKD", 4) == 0) &&
- (!dasd_info.FBA_layout)) {
+ if ((strncmp(info->dasd_info.type, "ECKD", 4) == 0) &&
+ (!info->dasd_info.FBA_layout)) {
/* OS/390 and zOS compatible disk layout */
- vtoc_read_volume_label(devname, dasd_info.label_block * blksize, &vlabel);
+ vtoc_read_volume_label(info->devname,
+ info->dasd_info.label_block * blksize,
+ &vlabel);
vtoc_volume_label_get_volser(&vlabel, volser);
return 0;
} else {
@@ -507,7 +480,6 @@ static void dasdfmt_write_labels(dasdfmt
unsigned int cylinders, unsigned int heads)
{
int label_position;
- dasd_information_t dasd_info;
struct hd_geometry geo;
format4_label_t f4;
format5_label_t f5;
@@ -520,11 +492,6 @@ static void dasdfmt_write_labels(dasdfmt
if (info->verbosity > 0)
printf("Retrieving dasd information... ");
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL "
- "BIODASDINFO failed (%s).\n",
- prog_name, strerror(errno));
-
if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET "
"failed (%s).\n", prog_name, strerror(errno));
@@ -586,14 +553,14 @@ static void dasdfmt_write_labels(dasdfmt
/* write VTOC */
vtoc_init_format4_label(&f4, geo.cylinders, cylinders, heads,
- geo.sectors, blksize, dasd_info.dev_type);
+ geo.sectors, blksize, info->dasd_info.dev_type);
vtoc_init_format5_label(&f5);
vtoc_init_format7_label(&f7);
vtoc_set_freespace(&f4, &f5, &f7, '+', 0, FIRST_USABLE_TRK,
(cylinders * heads - 1), cylinders, heads);
- label_position = dasd_info.label_block * blksize;
+ label_position = info->dasd_info.label_block * blksize;
if (info->verbosity > 0)
printf("Writing label...\n");
@@ -831,7 +798,6 @@ static void do_format_dasd(dasdfmt_info_
volume_label_t *vlabel)
{
char inp_buffer[5];
- dasd_information_t dasd_info;
struct dasd_eckd_characteristics *characteristics;
unsigned int cylinders, heads;
int count;
@@ -839,13 +805,9 @@ static void do_format_dasd(dasdfmt_info_
if (info->verbosity > 0)
printf("Retrieving disk geometry...\n");
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) "
- "IOCTL BIODASDINFO failed (%s).\n",
- prog_name, strerror(errno));
-
characteristics =
- (struct dasd_eckd_characteristics *) &dasd_info.characteristics;
+ (struct dasd_eckd_characteristics *)
+ &info->dasd_info.characteristics;
if (characteristics->no_cyl == LV_COMPAT_CYL &&
characteristics->long_no_cyl)
cylinders = characteristics->long_no_cyl;
@@ -878,8 +840,8 @@ static void do_format_dasd(dasdfmt_info_
if (!info->labelspec && !info->keep_volser) {
char buf[7];
- sprintf(buf, "0X%04x", info->devno);
- check_volser(buf, info->devno);
+ sprintf(buf, "0X%04x", info->dasd_info.devno);
+ check_volser(buf, info->dasd_info.devno);
vtoc_volume_label_set_volser(vlabel, buf);
}
@@ -959,7 +921,10 @@ static void do_format_dasd(dasdfmt_info_
int main(int argc, char *argv[])
{
- dasdfmt_info_t info;
+ dasdfmt_info_t info = {
+ .dasd_info = {0},
+ {0}
+ };
volume_label_t vlabel;
char old_volser[7];
@@ -986,7 +951,6 @@ int main(int argc, char *argv[])
prog_name = argv[0];
/* set default values */
- init_info(&info);
vtoc_volume_label_init(&vlabel);
format_params.blksize = DEFAULT_BLOCKSIZE;
@@ -1137,30 +1101,24 @@ int main(int argc, char *argv[])
if(info.yast_mode) {
for(i=0;i<dev_count;i++) {
- dasd_information_t dasd_info;
struct dasd_eckd_characteristics *characteristics;
unsigned int cylinders;
get_device_name(&info, dev_filename[i]);
- if ((filedes = open(info.devname, O_RDWR)) == -1) {
+
+ filedes = open(info.devname, O_RDWR);
+ if (filedes == -1) {
ERRMSG("%s: Unable to open device %s: %s\n",
- prog_name, info.devname, strerror(errno));
- free(dev_filename[i]);
- dev_filename[i]=(char*)-1; /* ignore device */
- continue;
- }
- if (ioctl(filedes, BIODASDINFO, &dasd_info) != 0) {
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (retrieving disk information) "
- "IOCTL BIODASDINFO failed (%s).\n",
- prog_name, strerror(errno));
+ prog_name, info.devname, strerror(errno));
free(dev_filename[i]);
dev_filename[i]=(char*)-1; /* ignore device */
- close(filedes);
continue;
}
+ get_device_info(&info);
+
characteristics =
- (struct dasd_eckd_characteristics *) &dasd_info.characteristics;
+ (struct dasd_eckd_characteristics *) &info.dasd_info.characteristics;
if (characteristics->no_cyl == LV_COMPAT_CYL &&
characteristics->long_no_cyl)
cylinders = characteristics->long_no_cyl;
@@ -1204,6 +1162,13 @@ int main(int argc, char *argv[])
get_device_name(&info, dev_filename[i]);
+ filedes = open(info.devname, O_RDWR);
+ if (filedes == -1)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
+ prog_name, info.devname, strerror(errno));
+
+ get_device_info(&info);
+
if (!info.blksize_specified)
format_params = ask_user_for_blksize(format_params);
@@ -1214,7 +1179,7 @@ int main(int argc, char *argv[])
exit(1);
}
- if (dasdfmt_get_volser(info.devname, old_volser) == 0)
+ if (dasdfmt_get_volser(&info, old_volser) == 0)
vtoc_volume_label_set_volser(&vlabel, old_volser);
else
ERRMSG_EXIT(EXIT_FAILURE,
@@ -1223,11 +1188,6 @@ int main(int argc, char *argv[])
}
- filedes = open(info.devname, O_RDWR);
- if (filedes == -1)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
- prog_name, info.devname, strerror(errno));
-
check_disk(&info);
if (check_param(str, ERR_LENGTH, &format_params) < 0)
--- a/dasdfmt/dasdfmt.h
+++ b/dasdfmt/dasdfmt.h
@@ -32,11 +32,11 @@
#define DASD_IOCTL_LETTER 'D'
/*
- * struct dasd_information_t
+ * struct dasd_information2_t
* represents any data about the device, which is visible to userspace.
* including format and features.
*/
-typedef struct dasd_information_t {
+typedef struct dasd_information2_t {
unsigned int devno; /* S/390 devno */
unsigned int real_devno; /* for aliases */
unsigned int schid; /* S/390 subchannel identifier */
@@ -56,7 +56,17 @@ typedef struct dasd_information_t {
unsigned int confdata_size;
char characteristics[64]; /* from read_device_characteristics */
char configuration_data[256]; /* from read_configuration_data */
-} dasd_information_t;
+ unsigned int format; /* format info like formatted/cdl/ldl/... */
+ unsigned int features; /* dasd features like 'ro',... */
+ unsigned int reserved0; /* reserved for further use ,... */
+ unsigned int reserved1; /* reserved for further use ,... */
+ unsigned int reserved2; /* reserved for further use ,... */
+ unsigned int reserved3; /* reserved for further use ,... */
+ unsigned int reserved4; /* reserved for further use ,... */
+ unsigned int reserved5; /* reserved for further use ,... */
+ unsigned int reserved6; /* reserved for further use ,... */
+ unsigned int reserved7; /* reserved for further use ,... */
+} dasd_information2_t;
struct dasd_eckd_characteristics {
@@ -165,7 +175,7 @@ typedef struct format_data_t {
#define BIODASDENABLE _IO(DASD_IOCTL_LETTER,1)
/* Get information on a dasd device (enhanced) */
-#define BIODASDINFO _IOR(DASD_IOCTL_LETTER,1,dasd_information_t)
+#define BIODASDINFO2 _IOR(DASD_IOCTL_LETTER, 3, dasd_information2_t)
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t)
@@ -251,9 +261,8 @@ typedef struct bootstrap2 {
} __attribute__ ((packed)) bootstrap2_t;
typedef struct dasdfmt_info {
- int devno;
+ dasd_information2_t dasd_info;
char devname[PATH_MAX];
- int usage_count;
int verbosity;
int testmode;
int withoutprompt;

View File

@ -0,0 +1,210 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Refactor do_format_dasd
In order to allow for new features to be integrated properly in the
existing code, certain parts of do_format_dasd() must be moved to
separate functions. This applies to setting VTOC information and
geometrical information.
Therefore, move the relevant bits to set_geo() and set_label().
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 132 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 76 insertions(+), 56 deletions(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -371,6 +371,73 @@ static int check_param(char *s, size_t b
}
/*
+ * Retrieve disk information and set cylinders and heads accordingly.
+ */
+static void set_geo(dasdfmt_info_t *info, unsigned int *cylinders,
+ unsigned int *heads)
+{
+ struct dasd_eckd_characteristics *characteristics;
+
+ if (info->verbosity > 0)
+ printf("Retrieving disk geometry...\n");
+
+ characteristics = (struct dasd_eckd_characteristics *)
+ &info->dasd_info.characteristics;
+ if (characteristics->no_cyl == LV_COMPAT_CYL &&
+ characteristics->long_no_cyl)
+ *cylinders = characteristics->long_no_cyl;
+ else
+ *cylinders = characteristics->no_cyl;
+ *heads = characteristics->trk_per_cyl;
+}
+
+/*
+ * Set VTOC label information
+ */
+static void set_label(dasdfmt_info_t *info, volume_label_t *vlabel,
+ format_data_t *p, unsigned int cylinders)
+{
+ char inp_buffer[5];
+
+ if (info->writenolabel) {
+ if (cylinders > LV_COMPAT_CYL && !info->withoutprompt) {
+ printf("\n--->> ATTENTION! <<---\n");
+ printf("You specified to write no labels to a"
+ " volume with more then %u cylinders.\n"
+ "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);
+ 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");
+ return;
+ }
+ }
+ } else {
+ if (!info->labelspec && !info->keep_volser) {
+ char buf[7];
+
+ sprintf(buf, "0X%04x", info->dasd_info.devno);
+ check_volser(buf, info->dasd_info.devno);
+ vtoc_volume_label_set_volser(vlabel, buf);
+ }
+
+ if (p->intensity & DASD_FMT_INT_COMPAT) {
+ info->cdl_format = 1;
+ vtoc_volume_label_set_label(vlabel, "VOL1");
+ vtoc_volume_label_set_key(vlabel, "VOL1");
+ vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01);
+ } else {
+ vtoc_volume_label_set_label(vlabel, "LNX1");
+ }
+ }
+}
+
+/*
* ask the user to specify a blocksize
*/
static format_data_t ask_user_for_blksize(format_data_t params)
@@ -452,7 +519,7 @@ static int dasdfmt_get_volser(dasdfmt_in
ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
prog_name, info->devname, strerror(errno));
- if (ioctl(f, BLKSSZGET, &blksize) != 0)
+ if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
"failed (%s).\n", prog_name, strerror(errno));
@@ -794,67 +861,16 @@ static void dasdfmt_prepare_and_format(d
disk_disabled = 0;
}
-static void do_format_dasd(dasdfmt_info_t *info, format_data_t *p,
- volume_label_t *vlabel)
+static void do_format_dasd(dasdfmt_info_t *info, volume_label_t *vlabel,
+ format_data_t *p, unsigned int cylinders,
+ unsigned int heads)
{
char inp_buffer[5];
- struct dasd_eckd_characteristics *characteristics;
- unsigned int cylinders, heads;
int count;
- if (info->verbosity > 0)
- printf("Retrieving disk geometry...\n");
-
- characteristics =
- (struct dasd_eckd_characteristics *)
- &info->dasd_info.characteristics;
- if (characteristics->no_cyl == LV_COMPAT_CYL &&
- characteristics->long_no_cyl)
- cylinders = characteristics->long_no_cyl;
- else
- cylinders = characteristics->no_cyl;
- heads = characteristics->trk_per_cyl;
-
p->start_unit = 0;
p->stop_unit = (cylinders * heads) - 1;
- if (info->writenolabel) {
- if (cylinders > LV_COMPAT_CYL && !info->withoutprompt) {
- printf("\n--->> ATTENTION! <<---\n");
- printf("You specified to write no labels to a"
- " volume with more then %u cylinders.\n"
- "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);
- 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");
- return;
- }
- }
- } else {
- if (!info->labelspec && !info->keep_volser) {
- char buf[7];
-
- sprintf(buf, "0X%04x", info->dasd_info.devno);
- check_volser(buf, info->dasd_info.devno);
- vtoc_volume_label_set_volser(vlabel, buf);
- }
-
- if (p->intensity & DASD_FMT_INT_COMPAT) {
- info->cdl_format = 1;
- vtoc_volume_label_set_label(vlabel, "VOL1");
- vtoc_volume_label_set_key(vlabel, "VOL1");
- vtoc_set_cchhb(&vlabel->vtoc, 0x0000, 0x0001, 0x01);
- } else {
- vtoc_volume_label_set_label(vlabel, "LNX1");
- }
- }
-
if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
dasdfmt_print_info(info, vlabel, cylinders, heads, p);
@@ -938,6 +954,7 @@ int main(int argc, char *argv[])
char *hashstep_str = NULL;
int rc, index, i;
+ unsigned int cylinders, heads;
int max_parallel=1;
int running=0;
@@ -1193,7 +1210,10 @@ int main(int argc, char *argv[])
if (check_param(str, ERR_LENGTH, &format_params) < 0)
ERRMSG_EXIT(EXIT_MISUSE, "%s: %s\n", prog_name, str);
- do_format_dasd(&info, &format_params, &vlabel);
+ set_geo(&info, &cylinders, &heads);
+ set_label(&info, &vlabel, &format_params, cylinders);
+ do_format_dasd(&info, &vlabel, &format_params,
+ cylinders, heads);
if (close(filedes) != 0)
ERRMSG("%s: error during close: %s\ncontinuing...\n",

View File

@ -0,0 +1,93 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Make the IOCTL BLKSSZGET reusable
The IOCTL BLKSSZGET is used to get blocksize information of a device.
Since it is used several times already and could be used for new
features as well, move the call to a separate function and make it
reusable.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -252,6 +252,17 @@ static void get_device_info(dasdfmt_info
}
/*
+ * Retrieve blocksize of device
+ */
+static void get_blocksize(unsigned int *blksize)
+{
+ if (ioctl(filedes, BLKSSZGET, blksize) != 0)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to get the blocksize "
+ "of the device failed (%s).\n", prog_name,
+ strerror(errno));
+}
+
+/*
* check for disk type and set some variables (e.g. usage count)
*/
static void check_disk(dasdfmt_info_t *info)
@@ -510,7 +521,7 @@ static void dasdfmt_print_info(dasdfmt_i
*/
static int dasdfmt_get_volser(dasdfmt_info_t *info, char *volser)
{
- int blksize;
+ unsigned int blksize;
int f;
volume_label_t vlabel;
@@ -519,9 +530,7 @@ static int dasdfmt_get_volser(dasdfmt_in
ERRMSG_EXIT(EXIT_FAILURE, "%s: Unable to open device %s: %s\n",
prog_name, info->devname, strerror(errno));
- if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (label pos) IOCTL BLKSSZGET "
- "failed (%s).\n", prog_name, strerror(errno));
+ get_blocksize(&blksize);
if (close(f) != 0)
ERRMSG("%s: error during close: %s\ncontinuing...\n",
@@ -551,7 +560,8 @@ static void dasdfmt_write_labels(dasdfmt
format4_label_t f4;
format5_label_t f5;
format7_label_t f7;
- int rc, blksize;
+ unsigned int blksize;
+ int rc;
void *ipl1_record, *ipl2_record;
int ipl1_record_len, ipl2_record_len;
@@ -559,9 +569,7 @@ static void dasdfmt_write_labels(dasdfmt
if (info->verbosity > 0)
printf("Retrieving dasd information... ");
- if (ioctl(filedes, BLKSSZGET, &blksize) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (write labels) IOCTL BLKSSZGET "
- "failed (%s).\n", prog_name, strerror(errno));
+ get_blocksize(&blksize);
/*
* Don't rely on the cylinders returned by HDIO_GETGEO, they might be

View File

@ -0,0 +1,555 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Add quick format support
On occasion, a DASD device might have been formatted earlier and could
potentially be re-initialized very easily. For device initalization it
is necessary to write disk information (i.e. volume label (CDL or LDL)
and VTOC) to the first two tracks. Currently you'd need to format the
entire disk, which can take a long time and is totally unnecessary.
Therefore, add a quick format mode which formats only the first two
tracks and fills them with data accordingly.
Before any formatting is done, several checks regarding the
expected device format are performed.
The mode can be specified with the new command line switch -M (--mode)
<mode>. Where 'mode' can be either 'full' (default) or 'quick'.
Document the switch -M (--mode) and its options full and quick in the
man page.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.8 | 15 ++
dasdfmt/dasdfmt.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
dasdfmt/dasdfmt.h | 51 +++++++++
3 files changed, 344 insertions(+), 12 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -67,7 +67,7 @@ Print version number and exit.
.TP
\fB-F\fR or \fB--force\fR
-Formats the device without checking, if the device is in use.
+Formats the device without performing sanity checking.
.TP
\fB-C\fR or \fB--check_host_count\fR
@@ -108,6 +108,19 @@ The value will be at least as big as the
.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
+.IP full
+Format the entire disk with the specified blocksize. (default)
+.IP quick
+Format the first two tracks and write label and partition information. Only use
+this option if you are sure that the target DASD already contains a regular
+format with the specified blocksize. A blocksize can optionally be specified
+using \fB-b\fR (\fB--blocksize\fR).
+.RE
+
+.TP
\fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
Number of cylinders to be processed in one formatting step.
The value must be an integer in the range 1 - 255.
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -30,6 +30,7 @@ static const char copyright_notice[] = "
static int filedes;
static int disk_disabled;
static format_data_t format_params;
+static format_mode_t mode;
char *prog_name;
volatile sig_atomic_t program_interrupt_in_progress;
int reqsize;
@@ -53,6 +54,7 @@ static void exit_usage(int exitcode)
" [-b <blocksize> | --blocksize=<blocksize>]\n"
" [-d <disk layout> | --disk_layout=<disk layout>]\n"
" [-r <cylinder> | --requestsize=<cylinder>]\n"
+ " [-M <mode> | --mode=<mode>]\n"
" <device>\n\n", prog_name);
printf(" -t or --test means testmode\n"
@@ -65,7 +67,7 @@ static void exit_usage(int exitcode)
" -r x or --requestsize=x means use x cylinders in one "
"format step\n"
" -v means verbose mode\n"
- " -F means don't check if the device is in use\n"
+ " -F means format without performing sanity checking\n"
" -k means keep volume serial\n"
" -C or --check_host_count means force dasdfmt to check\n"
" the host access open count to ensure the device\n"
@@ -79,7 +81,10 @@ static void exit_usage(int exitcode)
" <disk layout> is either\n"
" 'cdl' for compatible disk layout (default) or\n"
" 'ldl' for linux disk layout\n"
- " <device> device node of the device to format\n");
+ " <device> device node of the device to format\n"
+ " <mode> is either\n"
+ " 'full' to fully format the device (default)\n"
+ " 'quick' to format only the first two tracks\n");
exit(exitcode);
}
@@ -102,6 +107,131 @@ static int reread_partition_table(void)
}
/*
+ * Helper function for recs_per_track.
+ */
+static inline unsigned int ceil_quot(unsigned int d1, unsigned int d2)
+{
+ return (d1 + (d2 - 1)) / d2;
+}
+
+/*
+ * Calculate records per track depending on the device characteristics.
+ */
+static unsigned int recs_per_track(struct dasd_eckd_characteristics *rdc,
+ unsigned int kl, unsigned int dl)
+{
+ int dn, kn;
+
+ switch (rdc->dev_type) {
+ case 0x3380:
+ if (kl)
+ return 1499 / (15 + 7 + ceil_quot(kl + 12, 32) +
+ ceil_quot(dl + 12, 32));
+ else
+ return 1499 / (15 + ceil_quot(dl + 12, 32));
+ case 0x3390:
+ dn = ceil_quot(dl + 6, 232) + 1;
+ if (kl) {
+ kn = ceil_quot(kl + 6, 232) + 1;
+ return 1729 / (10 + 9 + ceil_quot(kl + 6 * kn, 34) +
+ 9 + ceil_quot(dl + 6 * dn, 34));
+ } else
+ return 1729 / (10 + 9 + ceil_quot(dl + 6 * dn, 34));
+ case 0x9345:
+ dn = ceil_quot(dl + 6, 232) + 1;
+ if (kl) {
+ kn = ceil_quot(kl + 6, 232) + 1;
+ return 1420 / (18 + 7 + ceil_quot(kl + 6 * kn, 34) +
+ ceil_quot(dl + 6 * dn, 34));
+ } else
+ return 1420 / (18 + 7 + ceil_quot(dl + 6 * dn, 34));
+ }
+ return 0;
+}
+
+/*
+ * Evaluate errors recognized by format checks and print appropriate error
+ * messages depending on the content of cdata.
+ */
+static void evaluate_format_error(dasdfmt_info_t *info, format_check_t *cdata,
+ unsigned int heads)
+{
+ struct dasd_eckd_characteristics *rdc;
+ /* Special blocksize values of the first 3 records of trk 0 of cyl 0 */
+ const int blksizes_trk0[] = { 24, 144, 80 };
+ /* Special blocksize value of trk 1 cyl 0 */
+ const int blksize_trk1 = 96;
+ unsigned int cyl;
+ unsigned int head;
+ unsigned int rpt;
+ unsigned int kl = 0;
+ int blksize = cdata->expect.blksize;
+
+ /*
+ * Reading record zero will never happen. If the record in error is 0
+ * nonetheless, the device is not formatted at all!
+ */
+ if (cdata->rec == 0) {
+ ERRMSG("WARNING: The specified device is not "
+ "formatted at all.\n");
+ return;
+ }
+
+ cyl = cdata->unit / heads;
+ head = cyl >> 16;
+ head <<= 4;
+ head |= cdata->unit % heads;
+
+ /*
+ * Set special expected values for the first 3 records of trk 0 of cyl 0
+ * and trk 1 of cyl 0 when checking a CDL formatted device.
+ */
+ if ((cdata->expect.intensity & DASD_FMT_INT_COMPAT) &&
+ cyl == 0 && head == 0 && cdata->rec < 4) {
+ kl = 4;
+ blksize = blksizes_trk0[cdata->rec - 1];
+ }
+ if ((cdata->expect.intensity & DASD_FMT_INT_COMPAT) &&
+ cyl == 0 && head == 1) {
+ kl = 44;
+ blksize = blksize_trk1;
+ }
+
+ rdc = (struct dasd_eckd_characteristics *)
+ &info->dasd_info.characteristics;
+
+ rpt = recs_per_track(rdc, kl, cdata->expect.blksize);
+
+ ERRMSG("WARNING: The specified device is not formatted as expected.\n");
+ switch (cdata->result) {
+ case DASD_FMT_ERR_TOO_FEW_RECORDS:
+ ERRMSG("Too few records (found %d, expected %d) "
+ "at cyl: %d trk: %d rec: %d.\n",
+ cdata->num_records, rpt, cyl, head, cdata->rec);
+ break;
+ case DASD_FMT_ERR_TOO_MANY_RECORDS:
+ ERRMSG("Too many records (found %d, expected %d) "
+ "at cyl: %d trk: %d rec: %d.\n",
+ cdata->num_records, rpt, cyl, head, cdata->rec);
+ break;
+ case DASD_FMT_ERR_BLKSIZE:
+ ERRMSG("Invalid blocksize (found %d, expected %d) "
+ "at cyl: %d trk: %d rec: %d.\n",
+ cdata->blksize, blksize, cyl, head, cdata->rec);
+ break;
+ case DASD_FMT_ERR_RECORD_ID:
+ ERRMSG("Invalid record ID at cyl: %d trk: %d rec: %d.\n",
+ cyl, head, cdata->rec);
+ break;
+ case DASD_FMT_ERR_KEY_LENGTH:
+ ERRMSG("Invalid key length (found %d, expected %d) "
+ "at cyl: %d trk: %d rec: %d.\n",
+ cdata->key_length, kl, cyl, head, cdata->rec);
+ break;
+ }
+}
+
+/*
* signal handler:
* enables the disk again in case of SIGTERM, SIGINT and SIGQUIT
*/
@@ -263,6 +393,25 @@ static void get_blocksize(unsigned int *
}
/*
+ * Check whether a specified blocksize matches the blocksize of the device
+ */
+static void check_blocksize(dasdfmt_info_t *info, unsigned int blksize)
+{
+ unsigned int dev_blksize;
+
+ if (!info->blksize_specified ||
+ info->dasd_info.format == DASD_FORMAT_NONE)
+ return;
+
+ get_blocksize(&dev_blksize);
+ if (dev_blksize != blksize) {
+ ERRMSG_EXIT(EXIT_FAILURE, "WARNING: Device is formatted with a "
+ "different blocksize (%d).\nUse --mode=full to "
+ "perform a clean format.\n", dev_blksize);
+ }
+}
+
+/*
* check for disk type and set some variables (e.g. usage count)
*/
static void check_disk(dasdfmt_info_t *info)
@@ -449,6 +598,35 @@ static void set_label(dasdfmt_info_t *in
}
/*
+ * This function checks whether a range of tracks is in regular format
+ * with the specified block size.
+ */
+static format_check_t check_track_format(format_data_t *p)
+{
+ format_check_t cdata = {
+ .expect = {
+ .blksize = p->blksize,
+ .intensity = p->intensity,
+ .start_unit = p->start_unit,
+ .stop_unit = p->stop_unit
+ }, 0
+ };
+
+ if (ioctl(filedes, BIODASDCHECKFMT, &cdata)) {
+ if (errno == ENOTTY) {
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Missing kernel support "
+ "for format checking (--force to "
+ "override)\n", prog_name);
+ }
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
+ prog_name, strerror(errno));
+ }
+
+ return cdata;
+}
+
+
+/*
* ask the user to specify a blocksize
*/
static format_data_t ask_user_for_blksize(format_data_t params)
@@ -511,6 +689,8 @@ static void dasdfmt_print_info(dasdfmt_i
printf(" Compatible Disk Layout : %s\n",
(p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
printf(" Blocksize : %d\n", p->blksize);
+ printf(" Mode : %s\n",
+ (mode == FULL) ? "Full" : "Quick");
if (info->testmode)
printf("Test mode active, omitting ioctl.\n");
@@ -869,6 +1049,62 @@ static void dasdfmt_prepare_and_format(d
disk_disabled = 0;
}
+/*
+ * This function will only format the first two tracks of a DASD.
+ * The rest of the DASD is untouched and left as is.
+ */
+static void dasdfmt_quick_format(dasdfmt_info_t *info, unsigned int cylinders,
+ unsigned int heads, format_data_t *p)
+{
+ format_check_t cdata = { .expect = {0}, 0 };
+ format_data_t tmp = *p;
+
+ if (info->force) {
+ printf("Skipping format check due to --force.\n");
+ } else {
+ check_blocksize(info, p->blksize);
+
+ printf("Checking the format of selected tracks...\n");
+
+ /* Check device format on the first and last 3 regular tracks */
+ tmp.start_unit = 2;
+ tmp.stop_unit = 4;
+ cdata = check_track_format(&tmp);
+ if (!cdata.result) {
+ tmp.start_unit = (cylinders * heads) - 3;
+ tmp.stop_unit = (cylinders * heads) - 1;
+ cdata = check_track_format(&tmp);
+ }
+ if (cdata.result) {
+ evaluate_format_error(info, &cdata, heads);
+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform "
+ "a clean format.\n");
+ } else {
+ printf("Done. Disk seems fine.\n");
+ }
+ }
+
+ if (!((info->withoutprompt) && (info->verbosity < 1)))
+ printf("Formatting the first two tracks of the device.\n");
+
+ /* Disable the device before we do anything */
+ if (ioctl(filedes, BIODASDDISABLE, p))
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to disable the device "
+ "failed. (%s)\n", prog_name, strerror(errno));
+ disk_disabled = 1;
+
+ /* Now do the actual formatting of our first two tracks */
+ if (ioctl(filedes, BIODASDFMT, p))
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to format the device "
+ "failed. (%s)\n", prog_name, strerror(errno));
+
+ /* Re-Enable the device so that we can continue working with it */
+ if (ioctl(filedes, BIODASDENABLE, p))
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl to enable the device "
+ "failed. (%s)\n", prog_name, strerror(errno));
+ disk_disabled = 0;
+}
+
static void do_format_dasd(dasdfmt_info_t *info, volume_label_t *vlabel,
format_data_t *p, unsigned int cylinders,
unsigned int heads)
@@ -877,7 +1113,15 @@ static void do_format_dasd(dasdfmt_info_
int count;
p->start_unit = 0;
- p->stop_unit = (cylinders * heads) - 1;
+
+ switch (mode) {
+ case FULL: /* all tracks */
+ p->stop_unit = (cylinders * heads) - 1;
+ break;
+ case QUICK: /* just the first two */
+ p->stop_unit = 1;
+ break;
+ }
if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
dasdfmt_print_info(info, vlabel, cylinders, heads, p);
@@ -919,11 +1163,17 @@ static void do_format_dasd(dasdfmt_info_
}
}
- if (!((info->withoutprompt) && (info->verbosity < 1)))
- printf("Formatting the device. This may take a "
- "while (get yourself a coffee).\n");
-
- dasdfmt_prepare_and_format(info, cylinders, heads, p);
+ switch (mode) {
+ case FULL:
+ if (!((info->withoutprompt) && (info->verbosity < 1)))
+ printf("Formatting the device. This may take a "
+ "while (get yourself a coffee).\n");
+ dasdfmt_prepare_and_format(info, cylinders, heads, p);
+ break;
+ case QUICK:
+ dasdfmt_quick_format(info, cylinders, heads, p);
+ break;
+ }
if (!info->yast_mode)
printf("Finished formatting the device.\n");
@@ -981,6 +1231,8 @@ int main(int argc, char *argv[])
format_params.blksize = DEFAULT_BLOCKSIZE;
format_params.intensity = DASD_FMT_INT_COMPAT;
+ mode = FULL;
+
/*************** parse parameters **********************/
while (1) {
@@ -1082,6 +1334,18 @@ int main(int argc, char *argv[])
case 'C':
info.force_host = 1;
break;
+ case 'M':
+ if (strcasecmp(optarg, "full") == 0)
+ mode = FULL;
+ else if (strcasecmp(optarg, "quick") == 0)
+ mode = QUICK;
+ else
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "%s: The specified mode '%s' is "
+ "invalid. Consult the man page for "
+ "more information.\n",
+ prog_name, optarg);
+ break;
case -1:
/* End of options string - start of devices list */
info.device_id = optind;
@@ -1194,8 +1458,14 @@ int main(int argc, char *argv[])
get_device_info(&info);
- if (!info.blksize_specified)
- format_params = ask_user_for_blksize(format_params);
+ /* Either let the user specify the blksize or get it from the kernel */
+ if (!info.blksize_specified) {
+ if (!(mode == FULL ||
+ info.dasd_info.format == DASD_FORMAT_NONE))
+ get_blocksize(&format_params.blksize);
+ else
+ format_params = ask_user_for_blksize(format_params);
+ }
if (info.keep_volser) {
if (format_params.intensity == 0x00) {
--- a/dasdfmt/dasdfmt.h
+++ b/dasdfmt/dasdfmt.h
@@ -143,6 +143,14 @@ struct dasd_eckd_characteristics {
unsigned int long_no_cyl;
} __attribute__ ((packed));
+/*
+ * Represents possible format modes that can be specified when formatting
+ * a DASD.
+ */
+typedef enum format_mode_t {
+ FULL, /* default mode */
+ QUICK, /* format only the first 2 tracks */
+} format_mode_t;
/*
* struct format_data_t
@@ -168,6 +176,43 @@ typedef struct format_data_t {
#define DASD_FMT_INT_COMPAT 8 /* use OS/390 compatible disk layout */
#define DASD_FMT_INT_FMT_NOR0 16 /* remove permission to write record zero */
+/*
+ * struct format_check_t
+ * represents all data necessary to evaluate the format of
+ * different tracks of a dasd
+ */
+typedef struct format_check_t {
+ /* Input */
+ struct format_data_t expect;
+
+ /* Output */
+ unsigned int result; /* Error indication (DASD_FMT_ERR_*) */
+ unsigned int unit; /* Track that is in error */
+ unsigned int rec; /* Record that is in error */
+ unsigned int num_records; /* Records in the track in error */
+ unsigned int blksize; /* Block-size of first record in error */
+ unsigned int key_length; /* Key length of first record in error */
+} format_check_t;
+
+/*
+ * values to be used in format_check_t for indicating
+ * possible format errors
+ */
+#define DASD_FMT_ERR_TOO_FEW_RECORDS 1
+#define DASD_FMT_ERR_TOO_MANY_RECORDS 2
+#define DASD_FMT_ERR_BLKSIZE 3
+#define DASD_FMT_ERR_RECORD_ID 4
+#define DASD_FMT_ERR_KEY_LENGTH 5
+
+/*
+ * values to be used for dasd_information2_t.format
+ * 0x00: NOT formatted
+ * 0x01: Linux disc layout
+ * 0x02: Common disc layout
+ */
+#define DASD_FORMAT_NONE 0
+#define DASD_FORMAT_LDL 1
+#define DASD_FORMAT_CDL 2
/* Disable the volume (for Linux) */
#define BIODASDDISABLE _IO(DASD_IOCTL_LETTER,0)
@@ -180,6 +225,9 @@ typedef struct format_data_t {
/* #define BIODASDFORMAT _IOW(IOCTL_LETTER,0,format_data_t) , deprecated */
#define BIODASDFMT _IOW(DASD_IOCTL_LETTER,1,format_data_t)
+/* Check device format according to format_data_t */
+#define BIODASDCHECKFMT _IOWR(DASD_IOCTL_LETTER, 2, format_check_t)
+
/****************************************************************************
* SECTION: Further IOCTL Definitions (see fs.h and hdreq.h ) *
****************************************************************************/
@@ -225,7 +273,7 @@ typedef struct format_data_t {
if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
"is in invalid format\n",prog_name);}
-#define dasdfmt_getopt_string "b:n:l:f:d:m:r:hpQLtyvVFkCYP:"
+#define dasdfmt_getopt_string "b:n:l:f:d:m:M:r:hpQLtyvVFkCYP:"
static struct option dasdfmt_getopt_long_options[]=
{
@@ -247,6 +295,7 @@ static struct option dasdfmt_getopt_long
{ "keep_volser", 0, 0, 'k'},
{ "norecordzero", 0, 0, 'z'},
{ "check_host_count", 0, 0, 'C'},
+ { "mode", 1, 0, 'M'},
{0, 0, 0, 0}
};

View File

@ -0,0 +1,279 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Make progress output reusable and add ETR
The progress indicator (in form of a progressbar, hashmarks or
percentages) is created within the formatting loop.
Put the drawing of the progress into a separate function to make it
reusable. Clean up the formatting loop while at it and make it
more readable. Also, add the estimated time remaining to the output.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.c | 198 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 138 insertions(+), 60 deletions(-)
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -11,6 +11,7 @@
#include <sys/utsname.h>
#include <linux/version.h>
+#include <sys/time.h>
#include "zt_common.h"
#include "dasdfmt.h"
@@ -20,6 +21,8 @@
#include <sys/wait.h>
#define BUSIDSIZE 8
+#define SEC_PER_DAY (60 * 60 * 24)
+#define SEC_PER_HOUR (60 * 60)
/* Full tool name */
static const char tool_name[] = "dasdfmt: zSeries DASD format program";
@@ -88,6 +91,120 @@ static void exit_usage(int exitcode)
exit(exitcode);
}
+/*
+ * Helper function to calculate the days, hours, minutes, and seconds
+ * for a given timestamp in seconds
+ */
+static void calc_time(time_t time, int *d, int *h, int *m, int *s)
+{
+ *d = time / SEC_PER_DAY;
+ time %= SEC_PER_DAY;
+ *h = time / SEC_PER_HOUR;
+ time %= SEC_PER_HOUR;
+ *m = time / 60;
+ *s = time % 60;
+}
+
+/*
+ * This function calculates and prints the estimated time remaining.
+ */
+static void print_etr(int p_new, int started)
+{
+ static struct timeval start;
+ struct timeval now;
+ time_t time_elapsed;
+ time_t time_end;
+ int d, h, m, s;
+ static int p_init;
+ int p;
+
+ if (!started) {
+ gettimeofday(&start, NULL);
+ p_init = p_new;
+ }
+ gettimeofday(&now, NULL);
+ time_elapsed = now.tv_sec - start.tv_sec;
+
+ /*
+ * We might start somewhere in the middle with an initial percentage
+ * value of i.e. 60%. Therefore we need to calculate the relative
+ * percentage of p_new within that remaining range (100 - 60) in order
+ * to correctly estimate the remaining time.
+ */
+ if (p_init == 100)
+ p = p_init;
+ else
+ p = 100 * (p_new - p_init) / (100 - p_init);
+
+ if (p == 0)
+ time_end = time_elapsed;
+ else
+ time_end = time_elapsed * (100 - p) / p;
+
+ /* Calculate days, hours, minutes, and seconds */
+ calc_time(time_end, &d, &h, &m, &s);
+ if (p_new == 100)
+ calc_time(time_elapsed, &d, &h, &m, &s);
+
+ /* Avoid printing leading zeros */
+ if (d > 0)
+ printf(" [%dd %dh %dm %ds%-4s", d, h, m, s, "]");
+ else if (h > 0)
+ printf(" [%dh %dm %ds%-7s", h, m, s, "]");
+ else if (m > 0)
+ printf(" [%dm %ds%-6s", m, s, "]");
+ else if (s > 0 || p > 50)
+ printf(" [%ds%-5s", s, "]");
+ else
+ printf(" [--%-1s", "]");
+}
+
+/*
+ * Draw the progress indicator depending on what command line argument is set.
+ * This can either be a progressbar, hashmarks, or percentage.
+ */
+static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders)
+{
+ static int hashcount;
+ static int started;
+ static int p_old;
+ int p_new = 0;
+ int barlength;
+ int i;
+
+ if (info->print_progressbar) {
+ printf("cyl %7d of %7d |", cyl, cylinders);
+ p_new = cyl * 100 / cylinders;
+ if (p_new != p_old || !started) {
+ /* percent value has changed */
+ p_old = p_new;
+ barlength = cyl * 33 / cylinders;
+ for (i = 1; i <= barlength; i++)
+ printf("#");
+ for (i = barlength + 1; i <= 33; i++)
+ printf("-");
+ printf("|%3d%%", p_new);
+ print_etr(p_new, started);
+ started = 1;
+ }
+ printf("\r");
+ fflush(stdout);
+ }
+
+ if (info->print_hashmarks &&
+ (cyl / info->hashstep - hashcount) != 0) {
+ printf("%d|", info->procnum);
+ fflush(stdout);
+ hashcount++;
+ }
+
+ if (info->print_percentage) {
+ printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders,
+ cyl * 100 / cylinders);
+ fflush(stdout);
+ }
+}
+
static int reread_partition_table(void)
{
int i = 0;
@@ -906,9 +1023,10 @@ static void dasdfmt_write_labels(dasdfmt
static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
unsigned int heads, format_data_t *format_params)
{
- format_data_t format_step;
- int j, cyl, tmp, p1, p2, hashcount = 0;
- unsigned int k;
+ unsigned int step_value;
+ unsigned long cur_trk;
+ format_data_t step;
+ int cyl = 0;
if (info->print_hashmarks) {
if (info->hashstep < reqsize)
@@ -923,73 +1041,33 @@ static void dasdfmt_format(dasdfmt_info_
info->hashstep);
}
- format_step.blksize = format_params->blksize;
- format_step.intensity = format_params->intensity;
-
- k = 0;
- cyl = 1;
- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
- printf("\n");
-
- while (1) {
- p1 = -1;
- p2 = 0;
- if (k + heads * reqsize >= format_params->stop_unit)
- reqsize = 1;
- format_step.start_unit = k;
- format_step.stop_unit = k + reqsize * heads - 1;
+ step = *format_params;
+ cur_trk = format_params->start_unit;
- if (cyl == 1)
- format_step.start_unit += 1;
+ while (cur_trk < format_params->stop_unit) {
+ step_value = reqsize * heads - (cur_trk % heads);
+ step.start_unit = cur_trk;
+ if (cur_trk + reqsize * heads >= format_params->stop_unit)
+ step.stop_unit = format_params->stop_unit;
+ else
+ step.stop_unit = cur_trk + step_value - 1;
- if (ioctl(filedes, BIODASDFMT, &format_step) != 0)
+ if (ioctl(filedes, BIODASDFMT, &step) != 0)
ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL "
"BIODASDFMT failed. (%s)\n",
prog_name, strerror(errno));
- if (info->print_progressbar) {
- printf("cyl %7d of %7d |", cyl, cylinders);
- p2 = p1;
- p1 = cyl * 100 / cylinders;
- if (p1 != p2) {
- /* percent value has changed */
- tmp = cyl * 50 / cylinders;
- for (j = 1; j <= tmp; j++)
- printf("#");
- for (j = tmp + 1; j <= 50; j++)
- printf("-");
- printf("|%3d%%", p1);
- }
- printf("\r");
- fflush(stdout);
- }
-
- if (info->print_hashmarks)
- if ((cyl / info->hashstep - hashcount) != 0) {
- printf("%d|",info->procnum);
- fflush(stdout);
- hashcount++;
- }
-
- if (info->print_percentage) {
- printf("cyl %7d of %7d |%3d%%\n", cyl, cylinders,
- cyl*100/cylinders);
- fflush(stdout);
- }
+ cyl = cur_trk / heads + 1;
+ draw_progress(info, cyl, cylinders);
- if (k % heads == 0) {
- k += reqsize * heads;
- cyl += reqsize;
- } else {
- k += format_params->stop_unit % heads;
- }
-
- if (k > format_params->stop_unit)
- break;
+ cur_trk += step_value;
}
+ /* We're done, draw the 100% mark */
+ cyl = step.stop_unit / heads + 1;
+ draw_progress(info, cyl, cylinders);
if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
- printf("\n\n");
+ printf("\n");
}
static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,

View File

@ -0,0 +1,453 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Add command line argument --check
Provide a function to check a DASD volume for correct formatting. This
can be useful in cases where only a few tracks of a volume are
incorrectly formatted.
All tracks on the device are checked. In an error case, the check
process is stopped and appropriate messages are displayed.
The --check command line argument can be combined with either -P,
-p or -m to display progress on the console.
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.8 | 5 +
dasdfmt/dasdfmt.c | 244 ++++++++++++++++++++++++++++++++++++++++--------------
dasdfmt/dasdfmt.h | 4
3 files changed, 190 insertions(+), 63 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -121,6 +121,11 @@ using \fB-b\fR (\fB--blocksize\fR).
.RE
.TP
+\fB--check\fR
+Perform a complete format check on a DASD volume. A blocksize can be specified
+with \fB-b\fR (\fB--blocksize\fR).
+
+.TP
\fB-r\fR \fIcylindercount\fR or \fB--requestsize\fR=\fIcylindercount\fR
Number of cylinders to be processed in one formatting step.
The value must be an integer in the range 1 - 255.
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -76,7 +76,8 @@ static void exit_usage(int exitcode)
" the host access open count to ensure the device\n"
" is not online on another operating system instance\n"
" --norecordzero prevent storage server from modifying"
- " record 0\n\n"
+ " record 0\n"
+ " --check perform complete format check on device\n\n"
" <volser> is the volume identifier, which is converted\n"
" to EBCDIC and written to disk.\n"
" (6 characters, e.g. LNX001\n"
@@ -163,7 +164,8 @@ static void print_etr(int p_new, int sta
* Draw the progress indicator depending on what command line argument is set.
* This can either be a progressbar, hashmarks, or percentage.
*/
-static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders)
+static void draw_progress(dasdfmt_info_t *info, int cyl, unsigned int cylinders,
+ int aborted)
{
static int hashcount;
static int started;
@@ -175,7 +177,7 @@ static void draw_progress(dasdfmt_info_t
if (info->print_progressbar) {
printf("cyl %7d of %7d |", cyl, cylinders);
p_new = cyl * 100 / cylinders;
- if (p_new != p_old || !started) {
+ if (p_new != p_old || !started || aborted) {
/* percent value has changed */
p_old = p_new;
barlength = cyl * 33 / cylinders;
@@ -184,6 +186,8 @@ static void draw_progress(dasdfmt_info_t
for (i = barlength + 1; i <= 33; i++)
printf("-");
printf("|%3d%%", p_new);
+ if (aborted)
+ p_new = 100;
print_etr(p_new, started);
started = 1;
}
@@ -284,11 +288,17 @@ static void evaluate_format_error(dasdfm
unsigned int kl = 0;
int blksize = cdata->expect.blksize;
+ if (info->print_progressbar || info->print_hashmarks)
+ printf("\n");
+
/*
- * Reading record zero will never happen. If the record in error is 0
- * nonetheless, the device is not formatted at all!
+ * If mode is not QUICK and a device format couldn't be determined, the
+ * device is considered not formatted.
+ * Also, reading record zero will never happen. If the record in error
+ * is 0 nonetheless, the device is not formatted at all as well!
*/
- if (cdata->rec == 0) {
+ if ((info->dasd_info.format == DASD_FORMAT_NONE && mode != QUICK) ||
+ cdata->rec == 0) {
ERRMSG("WARNING: The specified device is not "
"formatted at all.\n");
return;
@@ -529,6 +539,35 @@ static void check_blocksize(dasdfmt_info
}
/*
+ * Check whether a specified layout matches the layout
+ * a device is formatted with.
+ */
+static void check_layout(dasdfmt_info_t *info, unsigned int intensity)
+{
+ char layout[4];
+
+ if (!info->layout_specified ||
+ info->dasd_info.format == DASD_FORMAT_NONE)
+ return;
+
+ if ((intensity & DASD_FMT_INT_COMPAT) &&
+ info->dasd_info.format == DASD_FORMAT_CDL)
+ return;
+
+ if (!(intensity & DASD_FMT_INT_COMPAT) &&
+ info->dasd_info.format == DASD_FORMAT_LDL)
+ return;
+
+ if (info->dasd_info.format == DASD_FORMAT_CDL)
+ sprintf(layout, "CDL");
+ if (info->dasd_info.format == DASD_FORMAT_LDL)
+ sprintf(layout, "LDL");
+
+ ERRMSG_EXIT(EXIT_FAILURE, "WARNING: Device is formatted with a "
+ "different layout (%s).\n", layout);
+}
+
+/*
* check for disk type and set some variables (e.g. usage count)
*/
static void check_disk(dasdfmt_info_t *info)
@@ -715,10 +754,29 @@ static void set_label(dasdfmt_info_t *in
}
/*
+ * Check whether hashsteps are within the correct interval.
+ */
+static void check_hashmarks(dasdfmt_info_t *info)
+{
+ if (info->print_hashmarks) {
+ if (info->hashstep < reqsize)
+ info->hashstep = reqsize;
+ if ((info->hashstep < 1) || (info->hashstep > 1000)) {
+ printf("Hashmark increment is not in range <1,1000>, "
+ "using the default.\n");
+ info->hashstep = 10;
+ }
+
+ printf("Printing hashmark every %d cylinders.\n",
+ info->hashstep);
+ }
+}
+
+/*
* This function checks whether a range of tracks is in regular format
* with the specified block size.
*/
-static format_check_t check_track_format(format_data_t *p)
+static format_check_t check_track_format(dasdfmt_info_t *info, format_data_t *p)
{
format_check_t cdata = {
.expect = {
@@ -731,9 +789,11 @@ static format_check_t check_track_format
if (ioctl(filedes, BIODASDCHECKFMT, &cdata)) {
if (errno == ENOTTY) {
- ERRMSG_EXIT(EXIT_FAILURE, "%s: Missing kernel support "
- "for format checking (--force to "
- "override)\n", prog_name);
+ ERRMSG("%s: Missing kernel support for format checking",
+ prog_name);
+ if (!info->check)
+ ERRMSG(" (--force to override)");
+ ERRMSG_EXIT(EXIT_FAILURE, ".\n");
}
ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
prog_name, strerror(errno));
@@ -742,6 +802,97 @@ static format_check_t check_track_format
return cdata;
}
+/*
+ * Either do the actual format or check depending on the check-value.
+ */
+static int process_tracks(dasdfmt_info_t *info, unsigned int cylinders,
+ unsigned int heads, format_data_t *format_params)
+{
+ format_check_t cdata = { .expect = {0}, 0};
+ format_data_t step = *format_params;
+ unsigned long step_value;
+ unsigned long cur_trk;
+ int cyl = 0;
+
+ check_hashmarks(info);
+
+ cur_trk = format_params->start_unit;
+
+ while (cur_trk < format_params->stop_unit) {
+ step_value = reqsize * heads - (cur_trk % heads);
+ step.start_unit = cur_trk;
+ if (cur_trk + heads * reqsize >= format_params->stop_unit)
+ step.stop_unit = format_params->stop_unit;
+ else
+ step.stop_unit = cur_trk + step_value - 1;
+
+ if (info->check) {
+ cdata = check_track_format(info, &step);
+ if (cdata.result) {
+ cyl = cur_trk / heads + 1;
+ draw_progress(info, cyl, cylinders, 1);
+ evaluate_format_error(info, &cdata, heads);
+ break;
+ }
+ } else {
+ if (ioctl(filedes, BIODASDFMT, &step) != 0)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: the ioctl call "
+ "to format tracks failed. (%s)\n",
+ prog_name, strerror(errno));
+ }
+
+ cyl = cur_trk / heads + 1;
+ draw_progress(info, cyl, cylinders, 0);
+
+ cur_trk += step_value;
+ }
+ /* We're done, draw the 100% mark */
+ if (!cdata.result) {
+ cyl = step.stop_unit / heads + 1;
+ draw_progress(info, cyl, cylinders, 0);
+ printf("\n");
+ }
+
+ return cdata.result;
+}
+
+/*
+ * This function checks the format of the entire disk.
+ */
+static void check_disk_format(dasdfmt_info_t *info, unsigned int cylinders,
+ unsigned int heads, format_data_t *check_params)
+{
+ check_params->start_unit = 0;
+ check_params->stop_unit = (cylinders * heads) - 1;
+
+ printf("Checking format of the entire disk...\n");
+
+ if (info->testmode) {
+ printf("Test mode active, omitting ioctl.\n");
+ return;
+ }
+
+ check_blocksize(info, check_params->blksize);
+ check_layout(info, check_params->intensity);
+
+ /*
+ * If no layout was specified, set the intensity
+ * according to what the layout seems to be.
+ */
+ if (!info->layout_specified) {
+ if (info->dasd_info.format == DASD_FORMAT_CDL)
+ check_params->intensity |= DASD_FMT_INT_COMPAT;
+ else if (info->dasd_info.format == DASD_FORMAT_LDL)
+ check_params->intensity &= ~DASD_FMT_INT_COMPAT;
+ }
+
+ if (process_tracks(info, cylinders, heads, check_params)) {
+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a "
+ "clean format.\n");
+ }
+
+ printf("Done. Disk is fine.\n");
+}
/*
* ask the user to specify a blocksize
@@ -1023,51 +1174,7 @@ static void dasdfmt_write_labels(dasdfmt
static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
unsigned int heads, format_data_t *format_params)
{
- unsigned int step_value;
- unsigned long cur_trk;
- format_data_t step;
- int cyl = 0;
-
- if (info->print_hashmarks) {
- if (info->hashstep < reqsize)
- info->hashstep = reqsize;
- if ((info->hashstep < 1) || (info->hashstep > 1000)) {
- printf("Hashmark increment is not in range <1,1000>, "
- "using the default.\n");
- info->hashstep = 10;
- }
-
- if(!info->yast_mode) printf("Printing hashmark every %d cylinders.\n",
- info->hashstep);
- }
-
- step = *format_params;
- cur_trk = format_params->start_unit;
-
- while (cur_trk < format_params->stop_unit) {
- step_value = reqsize * heads - (cur_trk % heads);
- step.start_unit = cur_trk;
- if (cur_trk + reqsize * heads >= format_params->stop_unit)
- step.stop_unit = format_params->stop_unit;
- else
- step.stop_unit = cur_trk + step_value - 1;
-
- if (ioctl(filedes, BIODASDFMT, &step) != 0)
- ERRMSG_EXIT(EXIT_FAILURE, "%s: (format cylinder) IOCTL "
- "BIODASDFMT failed. (%s)\n",
- prog_name, strerror(errno));
-
- cyl = cur_trk / heads + 1;
- draw_progress(info, cyl, cylinders);
-
- cur_trk += step_value;
- }
- /* We're done, draw the 100% mark */
- cyl = step.stop_unit / heads + 1;
- draw_progress(info, cyl, cylinders);
-
- if ((info->print_progressbar || info->print_hashmarks) && !info->yast_mode)
- printf("\n");
+ process_tracks(info, cylinders, heads, format_params);
}
static void dasdfmt_prepare_and_format(dasdfmt_info_t *info,
@@ -1082,6 +1189,10 @@ static void dasdfmt_prepare_and_format(d
| DASD_FMT_INT_INVAL)
};
+ if (!((info->withoutprompt) && (info->verbosity < 1)))
+ printf("Formatting the device. This may take a while "
+ "(get yourself a coffee).\n");
+
if (info->verbosity > 0)
printf("Detaching the device...\n");
@@ -1147,11 +1258,11 @@ static void dasdfmt_quick_format(dasdfmt
/* Check device format on the first and last 3 regular tracks */
tmp.start_unit = 2;
tmp.stop_unit = 4;
- cdata = check_track_format(&tmp);
+ cdata = check_track_format(info, &tmp);
if (!cdata.result) {
tmp.start_unit = (cylinders * heads) - 3;
tmp.stop_unit = (cylinders * heads) - 1;
- cdata = check_track_format(&tmp);
+ cdata = check_track_format(info, &tmp);
}
if (cdata.result) {
evaluate_format_error(info, &cdata, heads);
@@ -1243,9 +1354,6 @@ static void do_format_dasd(dasdfmt_info_
switch (mode) {
case FULL:
- if (!((info->withoutprompt) && (info->verbosity < 1)))
- printf("Formatting the device. This may take a "
- "while (get yourself a coffee).\n");
dasdfmt_prepare_and_format(info, cylinders, heads, p);
break;
case QUICK:
@@ -1337,6 +1445,7 @@ int main(int argc, char *argv[])
printf("%s is not a valid option!\n", optarg);
exit(1);
}
+ info.layout_specified = 1;
break;
case 'y':
info.withoutprompt = 1;
@@ -1424,6 +1533,9 @@ int main(int argc, char *argv[])
"more information.\n",
prog_name, optarg);
break;
+ case OPT_CHECK:
+ info.check = 1;
+ break;
case -1:
/* End of options string - start of devices list */
info.device_id = optind;
@@ -1539,7 +1651,7 @@ int main(int argc, char *argv[])
/* Either let the user specify the blksize or get it from the kernel */
if (!info.blksize_specified) {
if (!(mode == FULL ||
- info.dasd_info.format == DASD_FORMAT_NONE))
+ info.dasd_info.format == DASD_FORMAT_NONE) || info.check)
get_blocksize(&format_params.blksize);
else
format_params = ask_user_for_blksize(format_params);
@@ -1568,8 +1680,14 @@ int main(int argc, char *argv[])
set_geo(&info, &cylinders, &heads);
set_label(&info, &vlabel, &format_params, cylinders);
- do_format_dasd(&info, &vlabel, &format_params,
- cylinders, heads);
+
+ if (info.check) {
+ check_disk_format(&info, cylinders, heads,
+ &format_params);
+ } else {
+ do_format_dasd(&info, &vlabel, &format_params,
+ cylinders, heads);
+ }
if (close(filedes) != 0)
ERRMSG("%s: error during close: %s\ncontinuing...\n",
--- a/dasdfmt/dasdfmt.h
+++ b/dasdfmt/dasdfmt.h
@@ -273,6 +273,7 @@ typedef struct format_check_t {
if (*endptr) ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
"is in invalid format\n",prog_name);}
+#define OPT_CHECK 128
#define dasdfmt_getopt_string "b:n:l:f:d:m:M:r:hpQLtyvVFkCYP:"
static struct option dasdfmt_getopt_long_options[]=
@@ -296,6 +297,7 @@ static struct option dasdfmt_getopt_long
{ "norecordzero", 0, 0, 'z'},
{ "check_host_count", 0, 0, 'C'},
{ "mode", 1, 0, 'M'},
+ { "check", 0, 0, OPT_CHECK},
{0, 0, 0, 0}
};
@@ -328,6 +330,8 @@ typedef struct dasdfmt_info {
int device_id;
int keep_volser;
int force_host;
+ int layout_specified;
+ int check;
int yast_mode;
int procnum;
} dasdfmt_info_t;

View File

@ -0,0 +1,266 @@
Subject: [PATCH] [FEAT LS1501] dasdfmt: Add new formatting modes
From: Jan Höppner <hoeppner@linux.vnet.ibm.com>
Summary: dasdfmt: Add new formatting modes
Description: Introduce new formatting modes 'quick' and 'expand' to either
format an earlier formatted DASD that could potentially be
re-initialized very easily or format unformatted tracks at the
end of a device that was previously extended.
Also add the command line argument --check to provide a function
that checks a DASD volume for correct formatting.
Upstream-ID: -
Problem-ID: LS1501
Upstream-Description:
dasdfmt: Add expand format mode
If a DASD was extended, the format of the first part of the disk
can be assumed to be correct. Usually, a full format would be necessary
to ensure a fully functional disk. However, this would also format
the already formatted part resulting in the loss of the data stored in
that part.
Add an expand mode which will search for the start of the unformatted
area and begin formatting from there.
The mode is being specified by --mode=expand (or -M expand for short).
Furthermore:
- Add string array for the individual modes for output purposes
- Avoid writing labels when EXPAND mode is active since they can be
assumed to be correct
- Add man page description
Signed-off-by: Jan Höppner <hoeppner@linux.vnet.ibm.com>
---
dasdfmt/dasdfmt.8 | 7 +++
dasdfmt/dasdfmt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++-----
dasdfmt/dasdfmt.h | 5 ++
3 files changed, 123 insertions(+), 9 deletions(-)
--- a/dasdfmt/dasdfmt.8
+++ b/dasdfmt/dasdfmt.8
@@ -118,6 +118,13 @@ Format the first two tracks and write la
this option if you are sure that the target DASD already contains a regular
format with the specified blocksize. A blocksize can optionally be specified
using \fB-b\fR (\fB--blocksize\fR).
+.IP expand
+Format all unformatted tracks at the end of the target DASD. This mode assumes
+that tracks at the beginning of the DASD volume have already been correctly
+formatted, while a consecutive set of tracks at the end are unformatted. You can
+use this mode to make added space available for Linux use after dynamically
+increasing the size of a DASD volume. A blocksize can optionally be specified
+using \fB-b\fR (\fB--blocksize\fR).
.RE
.TP
--- a/dasdfmt/dasdfmt.c
+++ b/dasdfmt/dasdfmt.c
@@ -88,7 +88,9 @@ static void exit_usage(int exitcode)
" <device> device node of the device to format\n"
" <mode> is either\n"
" 'full' to fully format the device (default)\n"
- " 'quick' to format only the first two tracks\n");
+ " 'quick' to format only the first two tracks\n"
+ " 'expand' to format only the unformatted end"
+ " of a device\n");
exit(exitcode);
}
@@ -791,8 +793,11 @@ static format_check_t check_track_format
if (errno == ENOTTY) {
ERRMSG("%s: Missing kernel support for format checking",
prog_name);
- if (!info->check)
+ if (mode == EXPAND) {
+ ERRMSG(". Mode 'expand' cannot be used");
+ } else if (!info->check) {
ERRMSG(" (--force to override)");
+ }
ERRMSG_EXIT(EXIT_FAILURE, ".\n");
}
ERRMSG_EXIT(EXIT_FAILURE, "%s: Could no check format: %s\n",
@@ -957,8 +962,7 @@ static void dasdfmt_print_info(dasdfmt_i
printf(" Compatible Disk Layout : %s\n",
(p->intensity & DASD_FMT_INT_COMPAT) ? "yes" : "no");
printf(" Blocksize : %d\n", p->blksize);
- printf(" Mode : %s\n",
- (mode == FULL) ? "Full" : "Quick");
+ printf(" Mode : %s\n", mode_str[mode]);
if (info->testmode)
printf("Test mode active, omitting ioctl.\n");
@@ -1169,6 +1173,60 @@ static void dasdfmt_write_labels(dasdfmt
}
/*
+ * This function will search for the beginning of an unformatted area
+ * on the device. It checks selected tracks beforehand and makes sure
+ * that the device is formatted to a certain extent. Otherwise the
+ * process is terminated.
+ */
+static void dasdfmt_find_start(dasdfmt_info_t *info, unsigned int cylinders,
+ unsigned heads, format_data_t *format_params)
+{
+ format_check_t cdata;
+ unsigned int middle;
+ unsigned int left = 2;
+ unsigned int right = (cylinders * heads) - 1;
+ unsigned int first = left;
+
+ check_blocksize(info, format_params->blksize);
+
+ format_params->start_unit = 0;
+ format_params->stop_unit = 4;
+ cdata = check_track_format(info, format_params);
+
+ if (cdata.result) {
+ evaluate_format_error(info, &cdata, heads);
+ ERRMSG_EXIT(EXIT_FAILURE, "Use --mode=full to perform a "
+ "clean format.\n");
+ }
+
+ printf("Expansion mode active. Searching for starting position...\n");
+
+ while (left <= right) {
+ /* new track number to look at */
+ middle = left + ((right - left) / 2);
+
+ format_params->start_unit = middle;
+ format_params->stop_unit = middle;
+ cdata = check_track_format(info, format_params);
+ if (cdata.blksize != format_params->blksize) {
+ first = middle;
+ right = middle - 1;
+ } else {
+ left = middle + 1;
+ }
+ }
+
+ if (first == 2 && cdata.blksize == format_params->blksize)
+ ERRMSG_EXIT(EXIT_FAILURE,
+ "No unformatted part found, aborting.\n");
+
+ printf("Done. Unformatted part starts at track %d.\n", first);
+
+ /* return format_params with start_unit set to the correct value */
+ format_params->start_unit = first;
+}
+
+/*
* formats the disk cylinderwise
*/
static void dasdfmt_format(dasdfmt_info_t *info, unsigned int cylinders,
@@ -1239,6 +1297,40 @@ static void dasdfmt_prepare_and_format(d
}
/*
+ * This function will start the expand format process.
+ */
+static void dasdfmt_expand_format(dasdfmt_info_t *info, unsigned int cylinders,
+ unsigned int heads, format_data_t *p)
+{
+ if (!((info->withoutprompt) && (info->verbosity < 1)))
+ printf("Formatting the device. This may take a while "
+ "(get yourself a coffee).\n");
+
+ if (info->verbosity > 0)
+ printf("Detaching the device...\n");
+
+ if (ioctl(filedes, BIODASDDISABLE, p) != 0)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
+ "BIODASDDISABLE failed. (%s)\n", prog_name,
+ strerror(errno));
+ disk_disabled = 1;
+
+ dasdfmt_format(info, cylinders, heads, p);
+
+ if (info->verbosity > 0)
+ printf("Formatting tracks complete...\n");
+
+ if (info->verbosity > 0)
+ printf("Re-accessing the device...\n");
+
+ if (ioctl(filedes, BIODASDENABLE, p) != 0)
+ ERRMSG_EXIT(EXIT_FAILURE, "%s: (prepare device) IOCTL "
+ "BIODASDENABLE failed. (%s)\n", prog_name,
+ strerror(errno));
+ disk_disabled = 0;
+}
+
+/*
* This function will only format the first two tracks of a DASD.
* The rest of the DASD is untouched and left as is.
*/
@@ -1310,6 +1402,10 @@ static void do_format_dasd(dasdfmt_info_
case QUICK: /* just the first two */
p->stop_unit = 1;
break;
+ case EXPAND: /* only the end of the disk */
+ dasdfmt_find_start(info, cylinders, heads, p);
+ p->stop_unit = (cylinders * heads) - 1;
+ break;
}
if ((info->verbosity > 0) || !info->withoutprompt || info->testmode)
@@ -1338,10 +1434,12 @@ static void do_format_dasd(dasdfmt_info_
if (!info->testmode) {
if (!info->withoutprompt) {
- printf("\n--->> ATTENTION! <<---\n");
- printf("All data of that device will be lost.\nType "
- "\"yes\" to continue, no will leave the disk "
- "untouched: ");
+ printf("\n");
+ if (mode != EXPAND)
+ printf("--->> ATTENTION! <<---\nAll data of "
+ "that device will be lost.\n");
+ 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") &&
@@ -1359,12 +1457,14 @@ static void do_format_dasd(dasdfmt_info_
case QUICK:
dasdfmt_quick_format(info, cylinders, heads, p);
break;
+ case EXPAND:
+ dasdfmt_expand_format(info, cylinders, heads, p);
}
if (!info->yast_mode)
printf("Finished formatting the device.\n");
- if (!info->writenolabel)
+ if (!(info->writenolabel || mode == EXPAND))
dasdfmt_write_labels(info, vlabel, cylinders, heads);
if (!info->yast_mode)
@@ -1526,6 +1626,8 @@ int main(int argc, char *argv[])
mode = FULL;
else if (strcasecmp(optarg, "quick") == 0)
mode = QUICK;
+ else if (strcasecmp(optarg, "expand") == 0)
+ mode = EXPAND;
else
ERRMSG_EXIT(EXIT_FAILURE,
"%s: The specified mode '%s' is "
--- a/dasdfmt/dasdfmt.h
+++ b/dasdfmt/dasdfmt.h
@@ -150,8 +150,13 @@ struct dasd_eckd_characteristics {
typedef enum format_mode_t {
FULL, /* default mode */
QUICK, /* format only the first 2 tracks */
+ EXPAND, /* search for unformatted area and format only that part*/
} format_mode_t;
+static const char mode_str[3][10] = {
+ "Full", "Quick", "Expand"
+};
+
/*
* struct format_data_t
* represents all data necessary to format a dasd

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,72 @@
Subject: [PATCH] [FEAT RTL1601] dbginfo.sh: Make use of sysfs collection helper
From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Summary: dbginfo.sh: Make use of sysfs collection helper
Description: If available, use dump2tar in dbginfo.sh for sysfs
file collection to significantly speed up dbginfo.sh
processing. Example speedup on an LPAR with ~190k
sysfs files:
Unpatched:
# time ./dbginfo.sh
real 1m19.624s
user 0m44.985s
sys 0m45.173s
Patched:
# time ./dbginfo.sh
real 0m5.822s
user 0m4.523s
sys 0m2.636s
Upstream-ID: -
Problem-ID: RTL1601
Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
---
scripts/dbginfo.sh | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
--- a/scripts/dbginfo.sh
+++ b/scripts/dbginfo.sh
@@ -620,20 +620,29 @@ collect_sysfs() {
fi
fi
- call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}"
+ # Collect sysfs files using multiple threads (-J 1) while excluding
+ # files known to block on read (-x). Stop reading a file that takes
+ # more than 5 seconds (-T 5) such as an active ftrace buffer.
+ dump2tar /sys -z -o "${WORKPATH}/sysfs.tgz" -x '*/tracing/trace_pipe*' \
+ -x '*/tracing/per_cpu/*' --ignore-failed-read -J 1 -T 5
- find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do
- mkdir -p "${WORKPATH}${dir_name}"
- done
+ if [ $? -ne 0 ] ; then
+ echo "${SCRIPTNAME}: Warning: dump2tar failed or is unavailable - falling back to slow path"
+ call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}"
- find /sys -noleaf -type f -perm /444\
- -a -not -name "*trace_pipe*"\
- 2>/dev/null | while IFS= read -r file_name; do
- echo " ${file_name}"
- if ! dd if="${file_name}" status=noxfer iflag=nonblock of="${WORKPATH}${file_name}" >/dev/null 2>&1; then
- echo "${SCRIPTNAME}: Warning: failed to copy \"${file_name}\""
- fi
- done
+ find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do
+ mkdir -p "${WORKPATH}${dir_name}"
+ done
+
+ find /sys -noleaf -type f -perm /444\
+ -a -not -name "*trace_pipe*"\
+ 2>/dev/null | while IFS= read -r file_name; do
+ echo " ${file_name}"
+ if ! dd if="${file_name}" status=noxfer iflag=nonblock of="${WORKPATH}${file_name}" >/dev/null 2>&1; then
+ echo "${SCRIPTNAME}: Warning: failed to copy \"${file_name}\""
+ fi
+ done
+ fi
if test ${debugfs_mounted} -eq 1; then
umount "${MOUNT_POINT_DEBUGFS}"

View File

@ -0,0 +1,558 @@
Subject: [PATCH] [FEAT LS1502] lsdasd/tunedasd: Add channel path aware erp
From: Stefan Haberland <sth@linux.vnet.ibm.com>
Summary: lsdasd/tunedasd: Add channel path aware erp
Description: Add tools support for channel path aware error recovery.
lsdasd shows the newly added IFCC path mask and HPF availability.
tunedasd gets an option to reset channel paths for a device.
Upstream-ID: -
Problem-ID: LS1502
Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com>
---
include/dasd_sys.h | 1
libdasd/dasd_sys.c | 94 +++++++++++++++++++++++++++++++++++++
tunedasd/include/disk.h | 3 -
tunedasd/man/tunedasd.8 | 17 ++++++
tunedasd/src/Makefile | 2
tunedasd/src/disk.c | 35 ++++++++++++++
tunedasd/src/tunedasd.c | 120 ++++++++++++++++++++++++++++--------------------
zconf/lsdasd | 36 +++++++++++---
8 files changed, 251 insertions(+), 57 deletions(-)
--- a/include/dasd_sys.h
+++ b/include/dasd_sys.h
@@ -13,5 +13,6 @@
#include "u2s.h"
int dasd_sys_raw_track_access(char *);
+int dasd_reset_chpid(char *, char *);
#endif /* DASD_SYS_H */
--- a/libdasd/dasd_sys.c
+++ b/libdasd/dasd_sys.c
@@ -6,6 +6,9 @@
* Copyright IBM Corp. 2016
*/
+#include <stdlib.h>
+#include <errno.h>
+
#include "dasd_sys.h"
/**
@@ -44,3 +47,94 @@ int dasd_sys_raw_track_access(char *devn
return (rc == 1) ? 1 : 0;
}
+
+
+int dasd_get_pm_from_chpid(char *busid, unsigned int chpid, int *mask)
+{
+ unsigned int val;
+ char path[40];
+ int count, i;
+ FILE *fp;
+
+ sprintf(path, "/sys/bus/ccw/devices/%s/../chpids", busid);
+ *mask = 0;
+ fp = fopen(path, "r");
+ if (!fp)
+ return ENODEV;
+
+ for (i = 0; i < 8; i++) {
+ count = fscanf(fp, " %x", &val);
+ if (count != 1) {
+ fclose(fp);
+ return EIO;
+ }
+ if (val == chpid)
+ *mask = 0x80 >> i;
+ }
+ fclose(fp);
+
+ return 0;
+}
+
+/**
+ * reset chpid
+ *
+ * The "devnode" parameter can be any valid relative or absolute path to
+ * a DASD device node, for example:
+ *
+ * - /dev/dasda
+ * - /dev/disk/by-path/ccw-0.0.bf20
+ *
+ * @param[in] devnode Device node of interest
+ * @param[in] chpid The chpid to reset
+ * If NULL all chpids will be reset
+ *
+ * @return 0 on success, otherwise one of the following error codes:
+ * - EINVAL No valid chpid specified.
+ * - ENODEV Could not open device.
+ * - ENOENT Specified chpid not found.
+ * - EIO Other I/O error
+ *
+ */
+int dasd_reset_chpid(char *devnode, char *chpid_char)
+{
+ unsigned int chpid;
+ char path[41];
+ char busid[9];
+ int mask, rc;
+ char *endptr;
+ FILE *fp;
+
+ if (u2s_getbusid(devnode, busid))
+ return ENODEV;
+
+ if (!chpid_char) {
+ sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid);
+ fp = fopen(path, "w");
+ if (!fp)
+ return ENODEV;
+ fprintf(fp, "%s", "all\n");
+ fclose(fp);
+ return 0;
+ }
+
+ errno = 0;
+ chpid = strtoul(chpid_char, &endptr, 16);
+ if (errno || (endptr && (*endptr != '\0')))
+ return EINVAL;
+
+ rc = dasd_get_pm_from_chpid(busid, chpid, &mask);
+ if (rc)
+ return rc;
+ if (!mask)
+ return ENOENT;
+
+ sprintf(path, "/sys/bus/ccw/devices/%s/path_reset", busid);
+ fp = fopen(path, "w");
+ if (!fp)
+ return ENODEV;
+ fprintf(fp, "%02x", mask);
+ fclose(fp);
+
+ return 0;
+}
--- a/tunedasd/include/disk.h
+++ b/tunedasd/include/disk.h
@@ -27,7 +27,8 @@ int disk_release (char* device);
int disk_slock (char* device);
int disk_query_reserve_status(char* device);
int disk_profile (char* device, char* prof_item);
-int disk_reset_prof (char* device);
+int disk_reset_prof(char *device);
+int disk_reset_chpid(char *device, char *chpid);
#endif /* not DISK_H */
--- a/tunedasd/man/tunedasd.8
+++ b/tunedasd/man/tunedasd.8
@@ -149,6 +149,18 @@ Following rows are supported:
.TP
.BR "\-R" " or " "\-\-reset_prof"
Reset profile info of device.
+.TP
+.BR "\-p" " or " "\-\-path_reset <chpid>"
+Reset a channel path <chpid> of a selected device. A channel path
+might be suspended due to high IFCC error rates or a High Performance
+FICON failure. Use this option to resume considering the channel path
+for I/O.
+.TP
+.BR "\-\-path_reset_all"
+Reset all channel paths of the selected device. The channel paths
+might be suspended due to high IFCC error rates or a High Performance
+FICON failure. Use this option to resume considering all defined
+channel paths for I/O.
.\"
.\".TP
.\".BR "\-o" " or " "\-\-online"
@@ -166,8 +178,13 @@ Reset profile info of device.
.br
tunedasd -c prestage -n 1 /dev/dasdc
+
+.br
+3. Scenario: Reset failed channel path with CHPID 45
.br
+ tunedasd -p 45 /dev/dasdc
+.br
.SH "SEE ALSO"
.BR dasdview (8),
.BR dasdfmt (8),
--- a/tunedasd/src/Makefile
+++ b/tunedasd/src/Makefile
@@ -5,7 +5,7 @@ includes = $(wildcard ../include/*.h)
all: tunedasd
-objects = tunedasd.o disk.o
+objects = tunedasd.o disk.o ../../libdasd/dasd_sys.o ../../libu2s/u2s.o
$(objects): $(includes)
tunedasd: $(objects)
--- a/tunedasd/src/disk.c
+++ b/tunedasd/src/disk.c
@@ -9,6 +9,7 @@
#include "disk.h"
#include "tunedasd.h"
+#include "dasd_sys.h"
#include <sys/types.h>
#include <sys/ioctl.h>
@@ -682,3 +683,37 @@ disk_reset_prof (char* device)
return 0;
}
+int disk_reset_chpid(char *device, char *chpid)
+{
+ int rc;
+
+ if (chpid)
+ printf("Resetting chpid %s for device <%s>...\n", chpid,
+ device);
+ else
+ printf("Resetting all chpids for device <%s>...\n", device);
+
+ rc = dasd_reset_chpid(device, chpid);
+ switch (rc) {
+ case 0:
+ printf("Done.\n");
+ return 0;
+ case ENODEV:
+ error_print("%s: %s", device, strerror(errno));
+ break;
+ case EINVAL:
+ error_print("%s: Could not reset chpid %s: Invalid CHPID",
+ device, chpid);
+ break;
+ case ENOENT:
+ error_print("%s: Could not reset chpid %s: CHPID not defined for device",
+ device, chpid);
+ break;
+ default:
+ error_print("%s: Could not reset chpid %s",
+ device, chpid);
+ break;
+ }
+
+ return -1;
+}
--- a/tunedasd/src/tunedasd.c
+++ b/tunedasd/src/tunedasd.c
@@ -34,28 +34,30 @@ static const char* usage_text[] = {
"(e.g. '/dev/dasda') or a list of devices separated by a space "
"character.",
"",
- "-h, --help Print this help, then exit",
- "-v, --version Print version information, then exit",
- "-g, --get_cache Get current storage server caching behaviour",
- "-c, --cache <behavior> Define caching behavior on storage server",
- " (normal/bypass/inhibit/sequential/prestage/"
- "record)",
- "-n, --no_cyl <n> Number of cylinders to be cached ",
- " (only valid together with --cache)",
- "-S, --reserve Reserve device",
- "-L, --release Release device",
- "-O, --slock Unconditional reserve device",
- " Note: Use with care, this breaks an existing "
- "lock",
- "-Q, --query_reserve Print reserve status of device ",
- "-P, --profile Print profile info of device",
- "-I, --prof_item Print single profile item",
- " (reqs/sects/sizes/total/totsect/start/irq/",
- " irqsect/end/queue)",
- "-R, --reset_prof Reset profile info of device"
+ "-h, --help Print this help, then exit",
+ "-v, --version Print version information, then exit",
+ "-g, --get_cache Get current storage server caching behaviour",
+ "-c, --cache <behavior> Define caching behavior on storage server",
+ " (normal/bypass/inhibit/sequential/prestage/"
+ "record)",
+ "-n, --no_cyl <n> Number of cylinders to be cached ",
+ " (only valid together with --cache)",
+ "-S, --reserve Reserve device",
+ "-L, --release Release device",
+ "-O, --slock Unconditional reserve device",
+ " Note: Use with care, this breaks an existing "
+ "lock",
+ "-Q, --query_reserve Print reserve status of device ",
+ "-P, --profile Print profile info of device",
+ "-I, --prof_item Print single profile item",
+ " (reqs/sects/sizes/total/totsect/start/irq/",
+ " irqsect/end/queue)",
+ "-R, --reset_prof Reset profile info of device",
+ "-p, --path_reset <chpid> Reset channel path <chpid> of a device",
+ " --path_reset_all Reset all channel paths of a device"
};
-#define CMD_KEYWORD_NUM 12
+#define CMD_KEYWORD_NUM 14
#define DEVICES_NUM 256
enum cmd_keyword_id {
@@ -71,6 +73,8 @@ enum cmd_keyword_id {
cmd_keyword_prof_item = 9,
cmd_keyword_reset_prof = 10,
cmd_keyword_query_reserve = 11,
+ cmd_keyword_path = 12,
+ cmd_keyword_path_all = 13,
};
@@ -79,18 +83,20 @@ static const struct {
char* keyword;
enum cmd_keyword_id id;
} keyword_list[] = {
- { "help", cmd_keyword_help },
- { "version", cmd_keyword_version },
- { "get_cache", cmd_keyword_get_cache },
- { "cache", cmd_keyword_cache },
- { "no_cyl", cmd_keyword_no_cyl },
- { "reserve", cmd_keyword_reserve },
- { "release", cmd_keyword_release },
- { "slock", cmd_keyword_slock },
- { "profile", cmd_keyword_profile },
- { "prof_item", cmd_keyword_prof_item },
- { "reset_prof", cmd_keyword_reset_prof },
- { "query_reserve", cmd_keyword_query_reserve }
+ { "help", cmd_keyword_help },
+ { "version", cmd_keyword_version },
+ { "get_cache", cmd_keyword_get_cache },
+ { "cache", cmd_keyword_cache },
+ { "no_cyl", cmd_keyword_no_cyl },
+ { "reserve", cmd_keyword_reserve },
+ { "release", cmd_keyword_release },
+ { "slock", cmd_keyword_slock },
+ { "profile", cmd_keyword_profile },
+ { "prof_item", cmd_keyword_prof_item },
+ { "reset_prof", cmd_keyword_reset_prof },
+ { "query_reserve", cmd_keyword_query_reserve },
+ { "path_reset", cmd_keyword_path },
+ { "path_reset_all", cmd_keyword_path_all }
};
@@ -103,22 +109,24 @@ enum cmd_key_state {
/* Determines which combination of keywords are valid */
enum cmd_key_state cmd_key_table[CMD_KEYWORD_NUM][CMD_KEYWORD_NUM] = {
- /* help vers get_ cach no_c rese rele sloc prof prof rese quer
- * ion cach e yl rve ase k ile _ite t_pr y_re
+ /* help vers get_ cach no_c rese rele sloc prof prof rese quer path path
+ * ion cach e yl rve ase k ile _ite t_pr y_re _all
* e m of serv
*/
- /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv },
- /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
- /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
- /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv },
- /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv },
- /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv },
- /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv },
- /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv },
- /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv },
- /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv },
- /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
- /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
+ /* help */ { req, opt, opt, opt, opt, opt, opt, opt, opt, opt, opt, inv, inv, inv },
+ /* version */ { inv, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
+ /* get_cache */ { opt, opt, req, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv },
+ /* cache */ { opt, opt, inv, req, opt, inv, inv, inv, inv, inv, inv, inv, inv, inv },
+ /* no_cyl */ { opt, opt, inv, req, req, inv, inv, inv, inv, inv, inv, inv, inv, inv },
+ /* reserve */ { opt, opt, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv, inv },
+ /* release */ { opt, opt, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv, inv },
+ /* slock */ { opt, opt, inv, inv, inv, inv, inv, req, inv, inv, inv, inv, inv, inv },
+ /* profile */ { opt, opt, inv, inv, inv, inv, inv, inv, req, opt, inv, inv, inv, inv },
+ /* prof_item */ { opt, opt, inv, inv, inv, inv, inv, inv, req, req, inv, inv, inv, inv },
+ /* reset_prof */ { opt, opt, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv, inv },
+ /* query_reserve */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv, inv },
+ /* path */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req, inv },
+ /* path_all */ { inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, inv, req },
};
struct parameter {
@@ -146,11 +154,13 @@ static struct option options[] = {
{ "prof_item", required_argument, NULL, 'I'},
{ "reset_prof", no_argument, NULL, 'R'},
{ "query_reserve", no_argument, NULL, 'Q'},
+ { "path_reset", required_argument, NULL, 'p'},
+ { "path_reset_all", no_argument, NULL, 'A'},
{ NULL, 0, NULL, 0 }
};
/* Command line option abbreviations */
-static const char option_string[] = "hvgc:n:SLOPI:RQ";
+static const char option_string[] = "hvgc:n:SLOPI:RQp:";
/* Error message string */
@@ -348,6 +358,14 @@ get_command_line (int argc, char* argv[]
optarg);
}
break;
+ case 'p':
+ rc = store_option(&cmdline, cmd_keyword_path,
+ optarg);
+ break;
+ case 'A':
+ rc = store_option(&cmdline, cmd_keyword_path_all,
+ optarg);
+ break;
case 'S':
rc = store_option (&cmdline, cmd_keyword_reserve,
optarg);
@@ -400,7 +418,6 @@ get_command_line (int argc, char* argv[]
return 0;
}
-
/*
* Execute the command.
*/
@@ -444,6 +461,13 @@ do_command (char* device, struct command
case cmd_keyword_query_reserve:
rc = disk_query_reserve_status(device);
break;
+ case cmd_keyword_path:
+ rc = disk_reset_chpid(device,
+ cmdline.parm[cmd_keyword_path].data);
+ break;
+ case cmd_keyword_path_all:
+ rc = disk_reset_chpid(device, NULL);
+ break;
default:
error_print ("Unknown command '%s' specified",
get_keyword_name (i));
--- a/zconf/lsdasd
+++ b/zconf/lsdasd
@@ -368,13 +368,15 @@ function extended()
CABLEPM=0
CUIRPM=0
HPFPM=0
+ IFCCPM=0
# additional information
read DIAG 2> /dev/null < $DEVPATH/use_diag || continue
read EER 2> /dev/null < $DEVPATH/eer_enabled || continue
read ERP 2> /dev/null < $DEVPATH/erplog || continue
+ read HPF 2> /dev/null < $DEVPATH/hpf
# in case the path_masks do not exist simply ignore it
- read OPM NPPM CABLEPM CUIRPM HPFPM 2> /dev/null < $DEVPATH/path_masks
+ read OPM NPPM CABLEPM CUIRPM HPFPM IFCCPM 2> /dev/null < $DEVPATH/path_masks
read -a C 2> /dev/null < $DEVPATH/../chpids || continue
read PIM PAM POM 2> /dev/null < $DEVPATH/../pimpampom || continue
@@ -385,6 +387,7 @@ function extended()
CABLEPM=0x$CABLEPM
CUIRPM=0x$CUIRPM
HPFPM=0x$HPFPM
+ IFCCPM=0x$IFCCPM
#-----------------------------------------------------------#
# aggregate chpids and path mask to useful information #
@@ -397,6 +400,7 @@ function extended()
CUIR_PATHS=(" " " " " " " " " " " " " " " ")
CABLE_PATHS=(" " " " " " " " " " " " " " " ")
HPF_PATHS=(" " " " " " " " " " " " " " " ")
+ IFCC_PATHS=(" " " " " " " " " " " " " " " ")
# installed paths
j=0
@@ -470,13 +474,25 @@ function extended()
(( mask>>=1 ))
done
+ # IFCC unusable paths
+ j=0
+ mask=0x80
+ for (( i=0; i<8; i++ )) ;do
+ PM=$(($IFCCPM&$mask))
+ if [ $PM -gt 0 ] ;then
+ IFCC_PATHS[j]=${C[$i]} ;
+ ((j++)) ;
+ fi
+ (( mask>>=1 ))
+ done
+
#-------------------------------------------#
# format data for output #
#-------------------------------------------#
if [[ "$ONLINE" == 0 ]]; then
ACTIVE="offline"
- printf "%s:%s:%s# status:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s#\n" \
+ printf "%s:%s:%s# status:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$ACTIVE" \
@@ -484,18 +500,20 @@ function extended()
"$READONLY" \
"$EER" \
"$ERP" \
+ "$HPF" \
"$DEV_UID" \
"${INSTALLED_PATHS[@]}" \
"${USED_PATHS[@]}" \
"${NP_PATHS[@]}" \
"${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \
- "${HPF_PATHS[@]}" ;
+ "${HPF_PATHS[@]}" \
+ "${IFCC_PATHS[@]}" ;
continue
elif [[ "$ALIAS" == 1 ]]; then
if [[ "$BASEONLY" == "false" ]]; then
ACTIVE="alias"
- printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s # uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s#\n" \
+ printf "%s:%s:%s# status:\t\t\t\t%s# type: \t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s # uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$ACTIVE" \
@@ -504,13 +522,15 @@ function extended()
"$READONLY" \
"$EER" \
"$ERP" \
+ "$HPF" \
"$DEV_UID" \
"${INSTALLED_PATHS[@]}" \
"${USED_PATHS[@]}" \
"${NP_PATHS[@]}" \
"${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \
- "${HPF_PATHS[@]}" ;
+ "${HPF_PATHS[@]}" \
+ "${IFCC_PATHS[@]}" ;
continue
else
continue
@@ -533,7 +553,7 @@ function extended()
COLON=":"
fi
- printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s#\n" \
+ printf "%s:%s:%s/%s/%s%s%s# status:\t\t\t\t%s# type: \t\t\t\t%s# blksz:\t\t\t\t%s# size: \t\t\t\t%s# blocks:\t\t\t\t%s# use_diag:\t\t\t\t%s# readonly:\t\t\t\t%s# eer_enabled:\t\t\t\t%s# erplog:\t\t\t\t%s# hpf:\t\t\t\t\t%s# uid: \t\t\t\t%s# paths_installed: \t\t\t%s %s %s %s %s %s %s %s# paths_in_use: \t\t\t%s %s %s %s %s %s %s %s# paths_non_preferred: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_cabling: \t\t%s %s %s %s %s %s %s %s# paths_cuir_quiesced: \t\t\t%s %s %s %s %s %s %s %s# paths_invalid_hpf_characteristics: \t%s %s %s %s %s %s %s %s# paths_error_threshold_exceeded: \t%s %s %s %s %s %s %s %s#\n" \
"$SORTKEYLEN" "$SORTKEY" \
"$BUSID" \
"$BLOCKNAME" \
@@ -549,13 +569,15 @@ function extended()
"$READONLY" \
"$EER" \
"$ERP" \
+ "$HPF" \
"$DEV_UID" \
"${INSTALLED_PATHS[@]}" \
"${USED_PATHS[@]}" \
"${NP_PATHS[@]}" \
"${CABLE_PATHS[@]}" \
"${CUIR_PATHS[@]}" \
- "${HPF_PATHS[@]}" ;
+ "${HPF_PATHS[@]}" \
+ "${IFCC_PATHS[@]}" ;
}
function host()

View File

@ -0,0 +1,30 @@
util_proc: Fix memory allocation error messages
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
---
libutil/util_proc.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
--- a/libutil/util_proc.c
+++ b/libutil/util_proc.c
@@ -54,8 +54,7 @@ util_proc_read_special_file(const char *
count = 0;
data = (char *) malloc(current_size);
if (data == NULL) {
- printf("Could not allocate %lld bytes of memory",
- (unsigned long long) size);
+ printf("Could not allocate %zu bytes of memory", current_size);
fclose(file);
return -1;
}
@@ -69,8 +68,8 @@ util_proc_read_special_file(const char *
if (count >= current_size) {
new_data = (char *) malloc(current_size * 2);
if (new_data == NULL) {
- printf("Could not allocate %lld bytes of memory",
- (unsigned long long) size);
+ printf("Could not allocate %zu bytes of memory",
+ current_size * 2);
free(data);
fclose(file);
return -1;

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.

2566
s390-tools.changes Normal file

File diff suppressed because it is too large Load Diff

484
s390-tools.spec Normal file
View File

@ -0,0 +1,484 @@
#
# spec file for package s390-tools
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
#
# 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 http://bugs.opensuse.org/
#
Name: s390-tools
Version: 1.34.0
Release: 0
Url: https://www.ibm.com/developerworks/linux/linux390/
Summary: S/390 tools like zipl and dasdfmt
License: GPL-2.0+ and BSD-2-Clause
Group: System/Kernel
BuildRequires: dracut
BuildRequires: fuse-devel
BuildRequires: gcc-c++
BuildRequires: gettext-tools
BuildRequires: glibc-devel-static
BuildRequires: kernel-zfcpdump
BuildRequires: libpfm-devel
BuildRequires: ncurses-devel
BuildRequires: net-snmp-devel
BuildRequires: qclib-devel
BuildRequires: tcpd-devel
BuildRequires: zlib-devel-static
PreReq: shadow %insserv_prereq %fillup_prereq dracut permissions
Requires: coreutils
Requires: gawk
Requires: perl-base
Requires: procps
Requires: rsync
Requires: tar
Requires: util-linux
Provides: s390utils:/sbin/dasdfmt
Source: s390-tools-%{version}.tar.bz2
Source1: s390-tools-rpmlintrc
Source2: zipl.conf
Source3: hsnc
Source4: sysconfig.hsnc
Source5: xpram
Source6: sysconfig.xpram
Source7: appldata
Source8: sysconfig.appldata
Source9: vmlogrdr
Source10: dasdro
Source11: dasd_reload
Source12: mkdump.pl
Source13: sysconfig.osasnmpd
Source14: zfcp_san_disc
Source15: mkdump.8
Source16: boot.cpi
Source17: sysconfig.cpi
Source18: zpxe.rexx
Source19: rules.xpram
Source20: rules.hw_random
Source21: 59-graf.rules
Source22: s390-tools-zdsfs.caution.txt
Source23: README.SUSE
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
Source31: detach_disks.sh
Source32: killcdl
Source33: lgr_check
Source34: sysconfig.virtsetup
Source35: virtsetup.service
Source36: virtsetup.sh
### 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
Source89: dasd_configure
Source90: iucv_configure
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
###
Patch1: s390-tools-sles12-zipl_boot_msg.patch
Patch2: s390-tools-sles12-sysconfig-compatible-dumpconf.patch
Patch3: s390-tools-sles12-create-filesystem-links.patch
Patch4: s390-tools-sles12-update-by_id-links-on-change-and-add-action.patch
Patch5: s390-tools-sles12sp2-feat-01-dasd-query-host.patch
Patch6: s390-tools-sles12-pardasdfmt.patch
Patch7: dasdfmt-retry-BIODASDINFO-if-device-is-busy.patch
Patch8: 59-dasd.rules-wait_for.patch
Patch9: s390-tools-sles12-fdasd-skip-partition-check-and-BLKRRPART-ioctl.patch
Patch10: s390-tools-sles12sp2-libu2s-Fix-busid-parsing.patch
Patch11: s390-tools-sles12sp2-chiucvallow-verify.patch
Patch12: s390-tools-sles12sp2-zipl-fix-failed-start-subchannel.patch
Patch13: s390-tools-sles12sp2-chreipl-virtio.patch
Patch14: s390-tools-sles12sp2-chzdev-disable-root-update.patch
Patch15: s390-tools-sles12sp2-lscss-allow-to-specify-devices-from-ssid-3.patch
Patch16: s390-tools-sles12sp3-dbginfo-01-libutil-Add-utility-functions.patch
Patch17: s390-tools-sles12sp3-dbginfo-02-dump2tar-Add-sysfs-collection-helper-for-dbginfo.sh-v2.patch
Patch18: s390-tools-sles12sp3-dbginfo-03-dbginfo.sh-Make-use-of-sysinfo-collection-helper.patch
Patch19: s390-tools-sles12sp3-lsdasd-tunedasd-Add-channel-path-aware-erp.patch
Patch20: s390-tools-sles12sp3-dasdfmt-01-Fix-behaviour-of-t-combined-with-y.patch
Patch21: s390-tools-sles12sp3-dasdfmt-02-Fix-trailing-whitespace.patch
Patch22: s390-tools-sles12sp3-dasdfmt-03-Apply-coding-convention.patch
Patch23: s390-tools-sles12sp3-dasdfmt-04-Use-enhanced-DASD-information.patch
Patch24: s390-tools-sles12sp3-dasdfmt-05-Refactor-do_format_dasd.patch
Patch25: s390-tools-sles12sp3-dasdfmt-06-Make-the-IOCTL-BLKSSZGET-reusable.patch
Patch26: s390-tools-sles12sp3-dasdfmt-07-Add-quick-format-support.patch
Patch27: s390-tools-sles12sp3-dasdfmt-08-Make-progress-output-reusable-and-add-ETR.patch
Patch28: s390-tools-sles12sp3-dasdfmt-09-Add-command-line-argument-check.patch
Patch29: s390-tools-sles12sp3-dasdfmt-10-Add-expand-format-mode.patch
Patch30: s390-tools-sles12sp3-util_proc-fix-memory-allocation-error-messages.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
ExclusiveArch: s390 s390x
%description
This package contains the tools needed to use Linux on IBM z Systems
and exploit many of the various capabilities of the hardware or z/VM.
For example:
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
%package -n osasnmpd
Summary: OSA-Express SNMP subagent
License: GPL-2.0+
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+ and SUSE-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
Group: System Environment/Base
Requires: fuse
%description hmcdrvfs
This package contains a HMC drive file system based on FUSE and a tool
to list files and directories.
%prep
%setup -q -n %{name}-%{version}
# SUSE patches
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
cp -vi %{S:22} CAUTION
%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="$RPM_OPT_FLAGS"
export KERNELIMAGE_MAKEFLAGS="%%{?_smp_mflags}"
make ZFCPDUMP_DIR=/usr/lib/s390-tools/zfcpdump DISTRELEASE=%{release}
gcc -static -o read_values ${OPT_FLAGS} %{S:86} -lqc
%install
mkdir -p $RPM_BUILD_ROOT/boot/zipl
%make_install \
ZFCPDUMP_DIR=/usr/lib/s390-tools/zfcpdump \
DISTRELEASE=%{release} \
SYSTEMDSYSTEMUNITDIR=%{_unitdir}
install -m 755 read_values $RPM_BUILD_ROOT/%{_bindir}/
install -m644 -t $RPM_BUILD_ROOT/%{_mandir}/man8 %{S:87}
export ROOT_BUILD_DIR="$RPM_BUILD_DIR/%{name}-%{version}/zfcpdump/kernel"
install -D -m600 /boot/image-*-zfcpdump $RPM_BUILD_ROOT/usr/lib/s390-tools/zfcpdump/zfcpdump_part.image
install -D -m644 etc/sysconfig/dumpconf $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.dumpconf
install -D -m755 etc/init.d/dumpconf $RPM_BUILD_ROOT/etc/init.d/dumpconf
install -D -m644 etc/udev/rules.d/40-z90crypt.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/40-z90crypt.rules
install -D -m644 etc/udev/rules.d/59-dasd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-dasd.rules
install -D -m644 etc/udev/rules.d/57-osasnmpd.rules $RPM_BUILD_ROOT/usr/lib/udev/rules.d/57-osasnmpd.rules
install -D -m644 etc/sysconfig/mon_statd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.mon_statd
install -D -m755 etc/init.d/mon_statd $RPM_BUILD_ROOT/etc/init.d/mon_statd
install -D -m644 etc/sysconfig/cpuplugd $RPM_BUILD_ROOT/var/adm/fillup-templates/sysconfig.cpuplugd
install -D -m755 etc/init.d/cpuplugd $RPM_BUILD_ROOT/etc/init.d/cpuplugd
mv iucvterm/doc/ts-shell/iucvconn_on_login $RPM_BUILD_ROOT/usr/bin/iucvconn_on_login
install -D -m644 %{S:26} $RPM_BUILD_ROOT/%{_unitdir}/cio_ignore.service
install -D -m755 %{S:27} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/setup_cio_ignore.sh
install -D -m755 %{S:31} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/detach_disks.sh
install -D -m644 %{S:35} $RPM_BUILD_ROOT/%{_unitdir}/virtsetup.service
install -D -m755 %{S:36} $RPM_BUILD_ROOT/usr/lib/systemd/scripts/virtsetup.sh
cp %{S:18} zpxe.rexx
cp %{S:2} zipl.conf.sample
cp %{S:23} README.SUSE
cd $RPM_BUILD_ROOT
install -D -m755 %{S:3} etc/init.d/hsnc
install -D -m644 %{S:4} var/adm/fillup-templates/sysconfig.hsnc
install -D -m755 %{S:5} etc/init.d/xpram
install -D -m644 %{S:6} var/adm/fillup-templates/sysconfig.xpram
install -D -m755 %{S:7} etc/init.d/appldata
install -D -m644 %{S:8} var/adm/fillup-templates/sysconfig.appldata
install -D -m755 %{S:9} etc/init.d/vmlogrdr
install -D -m755 %{S:10} sbin/dasdro
install -D -m755 %{S:11} sbin/dasd_reload
install -D -m755 %{S:12} sbin/mkdump
install -D -m644 %{S:13} var/adm/fillup-templates/sysconfig.osasnmpd
install -D -m755 %{S:14} sbin/zfcp_san_disc
install -D -m644 %{S:15} $RPM_BUILD_ROOT/%{_mandir}/man8
install -D -m755 %{S:16} etc/init.d/boot.cpi
install -D -m644 %{S:17} var/adm/fillup-templates/sysconfig.cpi
install -D -m644 %{S:19} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/52-xpram.rules
install -D -m644 %{S:20} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/52-hw_random.rules
install -D -m644 %{S:21} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-graf.rules
install -D -m644 %{S:28} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-prng.rules
install -D -m644 %{S:29} $RPM_BUILD_ROOT/usr/lib/udev/rules.d/59-zfcp-compat.rules
install -D -m644 %{S:30} $RPM_BUILD_ROOT/etc/modprobe.d/90-s390-tools.conf
install -D -m755 %{S:32} $RPM_BUILD_ROOT/sbin/killcdl
install -D -m755 %{S:33} $RPM_BUILD_ROOT/sbin/lgr_check
install -D -m644 %{S:34} var/adm/fillup-templates/sysconfig.virtsetup
if [ ! -d %{_sbindir} ]; then
rm -f %{_sbindir}
mkdir -p %{_sbindir}
fi
(cd usr/sbin; ln -s ../../etc/init.d/appldata rcappldata)
(cd usr/sbin; ln -s ../../etc/init.d/cpuplugd rccpuplugd)
(cd usr/sbin; ln -s ../../etc/init.d/dumpconf rcdumpconf)
(cd usr/sbin; ln -s ../../etc/init.d/hsnc rchsnc)
(cd usr/sbin; ln -s ../../etc/init.d/mon_statd rcmon_statd)
(cd usr/sbin; ln -s ../../etc/init.d/vmlogrdr rcvmlogrdr)
(cd usr/sbin; ln -s ../../etc/init.d/xpram rcxpram)
(cd usr/sbin; ln -s service rccio_ignore)
(cd usr/sbin; ln -s service rccpacfstatsd)
(cd usr/sbin; ln -s service rcvirtsetup)
if [ ! -d %{_bindir} ]; then
rm -f %{_bindir}
mkdir -p %{_bindir}
fi
install -D -m755 %{S:24} usr/bin/cputype
install -m644 -t $RPM_BUILD_ROOT/%{_mandir}/man8 %{S:25}
### Obsolete scripts and man pages to be removed once changes in other tools are made
install -m755 -t sbin/ %{S:88} %{S:89} %{S:90} %{S:91} %{S:92} %{S:93}
install -m644 -t $RPM_BUILD_ROOT/%{_mandir}/man8 %{S:94} %{S:95} %{S:96} %{S:97} %{S:98} %{S:99}
###
find . ! -type d |
%__sed 's/^.//;\-/man/-s/^.*$/%doc &.gz/' > %{_builddir}/%{name}-filelist
grep -v -E 'osasnmp|*\.conf$' %{_builddir}/%{name}-filelist >%{_builddir}/%{name}.list
grep osasnmp[^-] %{_builddir}/%{name}-filelist >%{_builddir}/%{name}.osasnmp
touch boot/zipl/active_devices.txt
mkdir -p usr/lib/net-snmp/agents
cd usr/lib/net-snmp/agents
cat <<EOT >osasnmpd
#!/bin/sh
PIDFILE=/var/run/osasnmpd.pid
function cleanup
{
rm -f \$PIDFILE
kill \`cat /var/run/osasnmpd.real.pid\`
}
. /etc/sysconfig/osasnmpd
trap cleanup 0
echo \$\$ >\$PIDFILE
/usr/sbin/osasnmpd -f -P /var/run/osasnmpd.real.pid \$OSASNMPD_PARAMETERS "\$@"
EOT
chmod 755 osasnmpd
%verifyscript
%verify_permissions -e /var/log/ts-shell
%pre
# check for ts-shell group or create it
getent group ts-shell >/dev/null 2>&1 || groupadd -r ts-shell
%service_add_pre cio_ignore.service
%service_add_pre cpacfstatsd.service
%service_add_pre virtsetup.service
%post
read INITPGM < /proc/1/comm
if [ "${INITPGM}" == "systemd" ]; then
echo "Running systemctl daemon-reload."
systemctl daemon-reload
fi
%set_permissions /var/log/ts-shell
# Create symbolic links to the scripts from setup and boot directories
%service_add_post cio_ignore.service
%service_add_post cpacfstatsd.service
%service_add_post virtsetup.service
# -i: skip insserv parts - has to be configured before use:
%{fillup_and_insserv -i -n appldata}
%{fillup_and_insserv -i -n cpuplugd}
%{fillup_and_insserv -i -n dumpconf}
%{fillup_and_insserv -i -n hsnc}
%{fillup_and_insserv -i -n mon_statd}
%{fillup_and_insserv -i -n vmlogrdr}
%{fillup_and_insserv -i -n virtsetup}
%{fillup_and_insserv -i -n xpram}
%{fillup_and_insserv -y -n cpi boot.cpi}
%triggerin -- kernel-default
grep -q '^/usr/bin/ts-shell$' /etc/shells \
|| echo "/usr/bin/ts-shell" >> /etc/shells
%post -n osasnmpd
%{fillup_and_insserv -i -n osasnmpd}
%preun
%{stop_on_removal appldata}
%{stop_on_removal cpuplugd}
%{stop_on_removal dumpconf}
%{stop_on_removal hsnc}
%{stop_on_removal mon_statd}
%{stop_on_removal vmlogrdr}
%{stop_on_removal xpram}
%service_del_preun cio_ignore.service
%service_del_preun cpacfstatsd.service
%service_del_preun virtsetup.service
%postun
%{restart_on_update boot.cpi}
%{restart_on_update appldata}
%{restart_on_update cpuplugd}
%{restart_on_update dumpconf}
%{restart_on_update hsnc}
%{restart_on_update mon_statd}
%{restart_on_update vmlogrdr}
%{restart_on_update xpram}
%service_del_postun cio_ignore.service
%service_del_postun cpacfstatsd.service
%service_del_postun virtsetup.service
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
%{insserv_cleanup}
if test x$1 = x0; then
# remove ts-shell from /etc/shells
grep -v '^/usr/bin/ts-shell$' /etc/shells > /etc/shells.ts-new
mv /etc/shells.ts-new /etc/shells
chmod 0644 /etc/shells
fi
%preun -n osasnmpd
%{stop_on_removal osasnmpd}
%clean
rm -rf $RPM_BUILD_ROOT
%files -f %{_builddir}/%{name}.list
%defattr(-,root,root)
%doc README
%doc README.SUSE
%doc iucvterm/doc/ts-shell
%doc zpxe.rexx
%doc zipl.conf.sample
%dir /etc/iucvterm
%config %attr(0640,root,ts-shell) /etc/iucvterm/ts-audit-systems.conf
%config %attr(0640,root,ts-shell) /etc/iucvterm/ts-authorization.conf
%config %attr(0640,root,ts-shell) /etc/iucvterm/ts-shell.conf
%config %attr(0640,root,ts-shell) /etc/iucvterm/unrestricted.conf
%config /etc/modprobe.d/90-s390-tools.conf
%config /boot/zipl/active_devices.txt
%dir %attr(2770,root,ts-shell) /var/log/ts-shell
%dir /etc/cmsfs-fuse
%config %attr(0640,root,root) /etc/cmsfs-fuse/filetypes.conf
%dir /usr/lib/s390-tools
%dir /usr/lib/s390-tools/zfcpdump
%dir /usr/lib/udev/rules.d
%dir /usr/lib/systemd/scripts
%dir %{_unitdir}
%dir /usr/share/s390-tools
%dir /usr/share/s390-tools/cpumf
%dir /boot/zipl
%dir /lib/s390-tools/
%exclude /usr/lib/udev/rules.d/57-osasnmpd.rules
%exclude /usr/bin/zdsfs
%exclude /usr/bin/hmcdrvfs
%exclude /usr/sbin/lshmc
%exclude %{_mandir}/man1/zdsfs.1.gz
%exclude %{_mandir}/man1/hmcdrvfs.1.gz
%exclude %{_mandir}/man8/lshmc.8.gz
%files -n osasnmpd -f %{_builddir}/%{name}.osasnmp
%defattr(-,root,root)
/usr/lib/net-snmp/agents/osasnmpd
%files zdsfs
%defattr(-,root,root)
%doc CAUTION
/usr/bin/zdsfs
/usr/share/man/man1/zdsfs.1.gz
%files hmcdrvfs
%defattr(-,root,root)
/usr/bin/hmcdrvfs
/usr/sbin/lshmc
%{_mandir}/man1/hmcdrvfs.1.gz
%{_mandir}/man8/lshmc.8.gz
%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"

22
sysconfig.cpi Normal file
View File

@ -0,0 +1,22 @@
## Path: Kernel/CPI
## Description: set Control Program Indentification data
## Type: list(yes,no)
## Default: no
#
# Set Control Program Identification data
#
CPI_SET="yes"
## Type: string
## Default: ""
#
# CPI system name
#
CPI_SYSTEM_NAME=""
## Type: string
## Default: ""
#
# CPI sysplex name
#
CPI_SYSPLEX_NAME=""

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"

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 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

98
vmlogrdr Normal file
View File

@ -0,0 +1,98 @@
#!/bin/sh
# Copyright (c) 2003 SUSE LINUX AG Nuernberg, Germany.
#
# Submit feedback to http://www.suse.de/feedback/
#
# /etc/init.d/vmlogrdr
#
# and symbolic its link
#
# /use/sbin/rcvmlogrdr
#
#
### BEGIN INIT INFO
# Provides: vmlogrdr
# Required-Start: $network $remote_fs
# Required-Stop: $null
# Default-Start: 3 5
# Default-Stop: 0 1 6
# Short-Description: Linux - z/VM Log reader
# Description: System startup script for the Linux - z/VM Log reader
### END INIT INFO
#
# Local settings
SERVICE=LOGREC
DEVNODE=/dev/vmlogrdr_${SERVICE}
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_failed <num> set local and overall rc status to <num><num>
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
. /etc/rc.status
# First reset status of this service
rc_reset
RETVAL=0
start() {
echo -n "Starting z/VM log reader for service $SERVICE... "
if [ -e $DEVNODE ]; then
echo -n "(already running)"
rc_status -v
rc_exit
fi
modprobe vmlogrdr 2>&1
if [ "$?" -ne 0 ] ; then
rc_failed 1
fi
rc_status -v
}
stop() {
echo "Stopping z/VM log reader for service $SERVICE... "
rmmod vmlogrdr
rc_status -v
}
restart() {
stop
start
}
status() {
echo -n "Checking z/VM log reader for service $SERVICE... "
if [ ! -e $DEVNODE ]; then
rc_failed 1
fi
rc_status -v
}
# How are we called?
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart|reload)
restart
;;
*)
echo "Usage: vmlogrdr {start|stop|status|restart|reload}"
RETVAL=1
esac
exit $RETVAL

278
xpram Normal file
View File

@ -0,0 +1,278 @@
#! /bin/sh
# Copyright (c) 2004 SUSE LINUX AG Nuernberg, Germany.
#
# Submit feedback to http://www.suse.de/feedback/
#
# /etc/init.d/xpram
#
# and symbolic its link
#
# /use/sbin/rcxpram
#
# System startup script for XPRAM device driver
#
### BEGIN INIT INFO
# Provides: xpram
# Required-Start: $remote_fs
# Required-Stop: $null
# Default-Start: 3 5
# Default-Stop: 0 1 6
# Short-Description: XPRAM device driver
# Description: Creates an xpram device and mounts it
### END INIT INFO
#
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:
rc_failed 6
rc_status -v
return 6
fi
}
prepare_xpram() {
if [ -z "$XPRAM_MNTPATH" -o -z "$XPRAM_DEVNODE" ]; then
echo -n "Cannot mkfs/mount XPRAM: Missing parameters! "
rc_failed 6
rc_status -v
rc_exit
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!"
rc_failed 6
rc_status -v
rc_exit
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 $?"
rc_failed 6
rc_status -v
rc_exit
fi
fi
}
# Shell functions sourced from /etc/rc.status:
# rc_check check and set local and overall rc status
# rc_status check and set local and overall rc status
# rc_status -v ditto but be verbose in local rc status
# rc_status -v -r ditto and clear the local rc status
# rc_failed set local and overall rc status to failed
# rc_failed <num> set local and overall rc status to <num><num>
# rc_reset clear local rc status (overall remains)
# rc_exit exit appropriate to overall rc status
. /etc/rc.status
# First reset status of this service
config_read=0
rc_reset
# 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! "
rc_failed 6
rc_status -v
rc_exit
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.
rc_exit
fi
}
check_enabled() {
if [ "$XPRAM_START" != "yes" ]; then
rc_failed 6
if [ "$XPRAM_MODULE" ]; then
if grep -q "$XPRAM_MODULE" /proc/modules; then
echo -n "Service $service $_rc_todo "
rc_status -v
fi
fi
rc_exit
fi
}
service="xpram"
case "$1" in
start)
# Read in configuration
read_config_file || rc_exit
check_enabled
quit_disabled
check_config
echo -n "Creating $service device "
modprobe "$XPRAM_MODULE"
if [ $? -ne 0 ]; then
echo -n "- failed to load $XPRAM_MODULE "
rc_failed 1
else
prepare_xpram
fi
# Remember status and be verbose
rc_status -v
;;
stop)
# Read in configuration
read_config_file || rc_exit
# 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"
rc_status
else
rc_failed 7
fi
# Remember status and be verbose
rc_status -v
;;
try-restart)
## Stop the service and if this succeeds (i.e. the
## service was running before), start it again.
## Note: try-restart is not (yet) part of LSB (as of 0.7.5)
$0 status >/dev/null && $0 restart
# Remember status and be quiet
rc_status
;;
restart)
## Stop the service and regardless of whether it was
## running or not, start it again.
$0 stop
$0 start
# Remember status and be quiet
rc_status
;;
force-reload)
echo -n "Force-reload $service "
$0 stop && $0 start
rc_status
;;
reload)
echo -n "Reloading $service not supported."
## it does not support reload:
rc_failed 3
rc_status -v
;;
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 || rc_exit
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"
rc_failed 3
fi
fi
else
rc_failed 3
fi
rc_status -v
;;
*)
echo "Usage: $0 {start|stop|status|try-restart|restart}"
exit 1
;;
esac
rc_exit

319
zfcp_disk_configure Normal file
View File

@ -0,0 +1,319 @@
#!/bin/sh
#
# zfcp_disk_configure
#
# Configures a zfcp disk
#
# 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 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 codes
# 1 sysfs not mounted
# 2 invalid value for <online>
# 3 device <ccwid> does not exist
# 4 WWPN invalid
# 5 Could not activate WWPN for adapter
# 6 Could not activate zFCP disk
# 7 SCSI disk could not be deactivated
# 8 zFCP LUN could not be deregistered
# 9 zFCP WWPN could not be deregistered
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
mesg () {
echo "$@"
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
if [ $# -ne 4 ] ; then
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 logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the device, in hexidecimal, with leading zeros."
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
udev_timeout=30
CCW_CHAN_ID=$1
FCP_WWPN=${2#0x*}
FCP_LUN=${3#0x*}
ONLINE=$4
# normalise to lower case
FCP_WWPN=`echo $FCP_WWPN | sed 's/A/a/g;s/B/b/g;s/C/c/g;s/D/d/g;s/E/e/g;s/F/f/g'`
FCP_LUN=`echo $FCP_LUN | sed 's/A/a/g;s/B/b/g;s/C/c/g;s/D/d/g;s/E/e/g;s/F/f/g'`
if [ -z "$CCW_CHAN_ID" ] ; then
mesg "No CCW device specified"
exit 1
fi
if [ -z "$ONLINE" ] || [ "$ONLINE" -ne "1" -a "$ONLINE" -ne "0" ]; then
mesg "Invalid device status $ONLINE"
exit 2
fi
_ccw_dir=${SYSFS}/bus/ccw/devices
_zfcp_dir="$_ccw_dir/$CCW_CHAN_ID"
if test ! -d "$_zfcp_dir" ; then
mesg "No device ${CCW_CHAN_ID}"
exit 3
fi
RULES_DIR=/etc/udev/rules.d
RULES_FILE=51-zfcp-${CCW_CHAN_ID}.rules
if [ ! -f ${RULES_DIR}/${RULES_FILE} ]; then
debug_mesg "No configuration file for adapter ${CCW_CHAN_ID}"
fi
# Check whether we need to do something
read allow_lun_scan < /sys/module/zfcp/parameters/allow_lun_scan
if [ "$allow_lun_scan" = "Y" ] ; then
for host in ${_zfcp_dir}/host* ; do
[ -d $host ] || continue
hba_num=${host##*host}
done
read port_type < /sys/class/fc_host/host${hba_num}/port_type
if [ "$port_type" = "NPIV VPORT" ] ; then
auto_lun_scan=1
fi
if [ -z "${hba_num}" ] ; then
if [ "$ONLINE" -eq "1" ]; then
debug_mesg "FCP adapter ${CCW_CHAN_ID} not configured"
exit 1
else
debug_mesg "FCP adapter ${CCH_CHAN_ID} already deconfigured"
exit 0
fi
fi
elif [ -d ${_zfcp_dir}/0x${FCP_WWPN}/0x${FCP_LUN} ]; then
if [ "$ONLINE" -eq "1" ]; then
debug_mesg "FCP disk ${FCP_WWPN}:${FCP_LUN} already configured"
exit 0
fi
else
if [ "$ONLINE" -eq "0" ]; then
debug_mesg "FCP disk ${FCP_WWPN}:${FCP_LUN} does not exist"
exit 0
fi
fi
if [ "$ONLINE" -eq "1" ]; then
# Configure SCSI disk
debug_mesg "Configuring FCP disk ${FCP_WWPN}:${FCP_LUN}"
# Check whether the wwpn exists
if [ "$auto_lun_scan" = 1 ] ; then
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" = "0x${FCP_WWPN}" ] ; then
for t in ${rport}/device/target* ; do
_targetid=${t#*target}
done
_zfcp_wwpn_dir=${rport}
break;
fi
done
else
_zfcp_wwpn_dir="${_zfcp_dir}/0x${FCP_WWPN}"
fi
if [ ! -d "${_zfcp_wwpn_dir}" ] ; then
mesg "WWPN ${FCP_WWPN} for adapter ${CCW_CHAN_ID} not found"
exit 5
fi
# Check and configure the zfcp-lun
if [ "$auto_lun_scan" = 1 ] ; then
if [ -n "${_targetid}" ] ; then
for _lun in /sys/class/scsi_device/${_targetid}:* ; do
[ -f ${_lun}/device/fcp_lun ] || continue
read _lunid < ${_lun}/device/fcp_lun
if [ "${_lunid}" = "0x${FCP_LUN}" ] ; then
_zfcp_lun_dir="${_lun}/device"
break;
fi
done
fi
if [ -z "$_zfcp_lun_dir" ] ; then
mesg "Could not activate FCP disk ${FCP_WWPN}:${FCP_LUN}"
exit 6
fi
else
# Check whether the WWPN is activated
if [ `cat ${_zfcp_wwpn_dir}/failed` -eq "1" ] ; then
mesg "WWPN ${FCP_WWPN} invalid."
exit 4
fi
if [ ! -d "${_zfcp_wwpn_dir}/0x${FCP_LUN}" ] ; then
echo "0x${FCP_LUN}" > ${_zfcp_wwpn_dir}/unit_add
/sbin/udevadm settle
fi
# Re-check whether the disk could be activated
if [ ! -d "${_zfcp_wwpn_dir}/0x${FCP_LUN}" ] ; then
mesg "Could not activate FCP disk ${FCP_WWPN}:${FCP_LUN}"
exit 6
fi
# Check for failed disks
read wwpn_status < ${_zfcp_wwpn_dir}/0x${FCP_LUN}/status
while [ "$wwpn_status" != 0 ] ; do
sleep 1
read wwpn_status < ${_zfcp_wwpn_dir}/0x${FCP_LUN}/in_recovery
[ "$wwpn_status" = 0 ] && break
done
read wwpn_status < ${_zfcp_wwpn_dir}/0x${FCP_LUN}/failed
if [ "$wwpn_status" = 1 ] ; then
debug_mesg "ERP failed on FCP disk ${FCP_WWPN}:${FCP_LUN}"
exit 7
fi
fi
else
# Deconfigure SCSI disk
debug_mesg "Deconfiguring FCP disk ${FCP_WWPN}:${FCP_LUN}"
_zfcp_wwpn_dir="${_zfcp_dir}/0x${FCP_WWPN}"
# Find the correspondig SCSI disk
for host_dir in $_zfcp_dir/host*; do
if [ -d $host_dir ] ; then
_zfcp_scsi_host_dir=$host_dir
break;
fi
done
if [ -d "$_zfcp_scsi_host_dir" ] ; then
# Deregister the disk from SCSI layer
for target in $_zfcp_scsi_host_dir/rport-*/target*/* ; do
[ "$target" != "${target##*/fc_transport}" ] && continue
if [ -d "$target" ] && [ -d "$target/scsi_device" ] ; then
_zfcp_scsi_id=${target##*/}
read _zfcp_tmp_hba < ${target}/hba_id
read _zfcp_tmp_wwpn < ${target}/wwpn
read _zfcp_tmp_lun < ${target}/fcp_lun
if [ "0x${FCP_LUN}" = "$_zfcp_tmp_lun" -a "0x${FCP_WWPN}" = "$_zfcp_tmp_wwpn" ] ; then
if [ "$auto_lun_scan" = 1 ] ; then
mesg "Could not deactivate SCSI disk ${_zfcp_scsi_id}"
exit 7
else
echo 1 > $target/delete
_zfcp_scsi_dir=$target
fi
break;
fi
fi
done
/sbin/udevadm settle
else
debug_mesg "No SCSI disk found for FCP disk ${FCP_WWPN}:${FCP_LUN}"
fi
# Re-check whether the SCSI disk is gone
num=$udev_timeout
while [ $num -gt 0 ] ; do
[ -d "${_zfcp_scsi_dir}" ] || break
let num=$num-1
sleep 1
done
if [ -d "${_zfcp_scsi_dir}" ]; then
mesg "Could not deactivate SCSI disk ${_zfcp_scsi_id}"
exit 7
fi
# Wait for udev to catch up
/sbin/udevadm settle
# check multipathing
_zfcp_scsi_dev=$(multipathd -k'show paths' 2> /dev/null | sed -n "s/$_zfcp_scsi_id \(sd[a-z]*\).*/\1/p")
[ "$_zfcp_scsi_dev" ] && multipathd -k"del path $_zfcp_scsi_dev"
# Deconfigure the FCP_LUN
: ${_zfcp_wwpn_dir}
echo "0x${FCP_LUN}" > ${_zfcp_wwpn_dir}/unit_remove
if [ -d "${_zfcp_wwpn_dir}/0x${FCP_LUN}" ]; then
mesg "Could not deregister FCP LUN ${FCP_LUN}"
exit 8
fi
# Find all remaining activated disks
ZFCP_LUNS=
for _tmp_wwpn_dir in ${_zfcp_dir}/0x*; do
if [ -d "$_tmp_wwpn_dir" ]; then
tmp_wwpn=$(basename $_tmp_wwpn_dir)
# Find all luns
for _tmp_lun_dir in ${_tmp_wwpn_dir}/0x*; do
if [ -d "$_tmp_lun_dir" ]; then
tmp_lun=$(basename $_tmp_lun_dir)
tmp_port="${tmp_wwpn}:${tmp_lun}"
ZFCP_LUNS="$ZFCP_LUNS
$tmp_port"
fi
done
fi
done
fi
# And now update the rules file
if test -d ${RULES_DIR}; then
# Find all WWPNs
read online < ${_zfcp_dir}/online;
if [ $online -eq 0 ] ; then
exit 0
fi
for port in ${_zfcp_dir}/0x* ; do
[ -d $port ] || continue;
[ -w $port/unit_remove ] || continue;
port_list="$port_list ${port##*/}"
done
cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configure zFCP device at ${CCW_CHAN_ID}
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CCW_CHAN_ID", IMPORT{program}="collect $CCW_CHAN_ID %k $CCW_CHAN_ID zfcp"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="zfcp", IMPORT{program}="collect $CCW_CHAN_ID %k $CCW_CHAN_ID zfcp"
ACTION=="add", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[ccw/$CCW_CHAN_ID]online}="1"
EOF
for port in $port_list; do
for lun in ${_zfcp_dir}/$port/0x* ; do
[ -d $lun ] || continue;
[ -r $lun/status ] || continue;
cat >> ${RULES_DIR}/${RULES_FILE} <<EOF
ACTION=="add", KERNEL=="rport-*", ATTR{port_name}=="$port", SUBSYSTEMS=="ccw", KERNELS=="$CCW_CHAN_ID", ATTR{[ccw/$CCW_CHAN_ID]$port/unit_add}="${lun##*/}"
EOF
done
done
fi
# EOF

125
zfcp_disk_configure.8 Normal file
View File

@ -0,0 +1,125 @@
.TH zfcp_disk_configure "8" "February 2013" "s390-tools"
.SH NAME
zfcp_disk_configure \- Configures or deconfigures a SCSI over zFCP disk (LUN).
.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 SCSI over zFCP disks. In addition to bringing the disk online or offline, it will also create or delete the necessary udev rules for the disk.
.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 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
.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 bring the adapter online or a literal 0 to take it offline
.SH FILES
.I /etc/udev/rules.d/51-zfcp-<ccwid>.rules
.RS
This file provides the udev rules necessary to activate a specific zFCP adapter and the LUNs associated with it. Rules relating to the zFCP adapter are added by the zfcp_host_configure(8) script.
.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 CCW device specified
.RS
This message should never be seen, since the script checks to make sure there are exactly four parameters specified. I.e., it is a sanity check. If it is seen, please open a bug report. Return code 1 is set.
.RE
.IP
.B Invalid device status ${ONLINE}
.RS
A value other than 0 or 1 was specified for the second parameter, online. Return code 2 is set.
.RE
.IP
.B No device ${CCW_CHAN_ID}
.RS
If 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 WWPN ${FCP_WWPN} invalid
.RS
Activation of the WWPN failed. Return code 4 is set.
.RE
.IP
.B WWPN ${FCP_WWPN} for adapter ${CCW_CHAN_ID} not found
.RS
The WWPN specified isn't being "seen" by the zFCP adapter. This could have a number of different causes, such as an incorrect configuration on the storage array or SAN switch, a typographical error entering this command, etc. Return code 5 is set.
.RE
.IP
.B Could not activate FCP disk ${FCP_WWPN}:${FCP_LUN}
.RS
An attempt was made to activate the specified LUN, which failed. Return code 6 is set.
.RE
.IP
.B Could not deactivate SCSI disk ${_zfcp_scsi_id}
.RS
An attempt was made to deactivate the specified LUN, which failed. Return code 7 is set.
.RE
.IP
.B Could not deregister FCP LUN ${FCP_LUN}
.RS
An attempt was made to remove the specified LUN from the zFCP adapter, which failed. Return code 8 is set.
.RE
If environment variable DEBUG is set to "yes," the following messages may be issued on stdout:
.IP
.B No configuration file for adapter ${CCW_CHAN_ID}
.RS
The /etc/udev/rules.d/51-zfcp-<ccwid>.rules file does not exist. No return code is set, and execution continues.
.RE
.IP
.B FCP disk ${FCP_WWPN}:${FCP_LUN} already configured
.RS
The parameters specified activating the LUN, but it was already activated. Return code 0 is set.
.RE
.IP
.B FCP disk ${FCP_WWPN}:${FCP_LUN} does not exist
.RS
The parameters specified deactivating the LUN, but it is not currently activated. Return code 0 is set.
.RE
.IP
.B Configuring FCP disk ${FCP_WWPN}:${FCP_LUN}
.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 ERP failed on FCP disk ${FCP_WWPN}:${FCP_LUN}
.RS
An attempt to bring the specified LUN online succeeded, but the device is marked as "failed" by the SCSI layer. Return code 7 is set.
.RE
.IP
.B Deconfiguring FCP disk ${FCP_WWPN}:${FCP_LUN}
.RS
Another bit of verbosity, which also just indicates that we got past certain error checks and will now try to do something useful.
.RE
.IP
.B No SCSI disk found for FCP disk ${FCP_WWPN}:${FCP_LUN}
.RS
This indicates that deactivating a SCSI disk was successful.
.RE
.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)

186
zfcp_host_configure Normal file
View File

@ -0,0 +1,186 @@
#!/bin/sh
#
# zfcp_host_configure
#
# Configures a zfcp host adapter
#
# 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 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 codes
# 1 sysfs not mounted
# 2 invalid value for <online>
# 3 device <ccwid> does not exist
# 4 module zfcp could not be loaded
# 5 adapter status could not be changed
# 6 wwpn ports still active
# 10 adapter active but allow_lun_scan active
#
if [ "${DEBUG}" != "yes" ]; then
DEBUG="no"
fi
DATUM=$(date)
add_channel_for_cio() {
echo "$* # $DATUM" >> /boot/zipl/active_devices.txt
}
remove_channel_for_cio() {
[ -w /boot/zipl/active_devices.txt ] && sed -i -e "/^$1/d" /boot/zipl/active_devices.txt
}
mesg () {
echo "$@"
}
debug_mesg () {
case "$DEBUG" in
yes) mesg "$@" ;;
*) ;;
esac
}
if [ $# -ne 2 ] ; then
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 logical channel subsystem (lcss) number. Most often this is 0, but it could be non-zero"
echo " ssss is the four digit subchannel address of the device, in hexidecimal, with leading zeros."
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
CCW_CHAN_ID=$1
ONLINE=$2
MODULE=zfcp
if [ -z "$CCW_CHAN_ID" ] ; then
mesg "No CCW device specified"
exit 1
fi
if [ -z "$ONLINE" ] || [ "$ONLINE" != "1" -a "$ONLINE" != "0" ]; then
mesg "Invalid device status $ONLINE"
exit 2
fi
_ccw_dir=${SYSFS}/bus/ccw/devices
_zfcp_dir="$_ccw_dir/$CCW_CHAN_ID"
if test ! -d "$_zfcp_dir" ; then
mesg "No device ${CCW_CHAN_ID}"
exit 3
fi
# Check whether we need to load the zfcp module
if test ! -d "${SYSFS}/bus/ccw/drivers/zfcp"; then
modprobe ${MODULE}
# Re-check whether module loading has succeeded
if test ! -d "${SYSFS}/bus/ccw/drivers/zfcp"; then
mesg "Could not load module ${MODULE}"
exit 4
fi
fi
RULES_DIR=/etc/udev/rules.d
RULES_FILE=51-zfcp-${CCW_CHAN_ID}.rules
ALREADY_ONLINE=0
# Check whether we need to do something
_zfcp_dev_status=$(cat $_zfcp_dir/online)
if [ "$_zfcp_dev_status" -eq "$ONLINE" ]; then
debug_mesg "zFCP adapter ${CCW_CHAN_ID} already in status ${ONLINE}"
ALREADY_ONLINE=1
fi
debug_mesg "Configuring device ${CCW_CHAN_ID}"
if [ -f ${RULES_DIR}/${RULES_FILE} ]; then
rm -f ${RULES_DIR}/${RULES_FILE}
fi
if [ "$ONLINE" -eq "1" ]; then
if [ "${ALREADY_ONLINE}" -eq "0" ]; then
# Activate the device
echo "$ONLINE" > $_zfcp_dir/online
# Now wait for the adapter to initialize
/sbin/udevadm settle
fi
for loop in 1 2 3 4 5 ; do
read status < /sys/bus/ccw/devices/$CCW_CHAN_ID/status
(( $status & 0x10000000 )) && break;
done
read wwpn_status < /sys/bus/ccw/devices/$CCW_CHAN_ID/status
if !(( $wwpn_status & 0x10000000 )) ; then
echo 0 > /sys/bus/ccw/devices/$CCW_CHAN_ID/online
mesg "Could not activate adapter, status $wwpn_status"
exit 5
fi
# Write the configuration file
if test -d ${RULES_DIR}; then
cat > ${RULES_DIR}/${RULES_FILE} <<EOF
# Configuration for the zfcp adapter at CCW ID ${CCW_CHAN_ID}
ACTION=="add", SUBSYSTEM=="ccw", KERNEL=="$CCW_CHAN_ID", IMPORT{program}="collect $CCW_CHAN_ID %k $CCW_CHAN_ID zfcp"
ACTION=="add", SUBSYSTEM=="drivers", KERNEL=="zfcp", IMPORT{program}="collect $CCW_CHAN_ID %k $CCW_CHAN_ID zfcp"
ACTION=="add", ENV{COLLECT_$CCW_CHAN_ID}=="0", ATTR{[ccw/$CCW_CHAN_ID]online}="1"
EOF
fi
add_channel_for_cio "${CCW_CHAN_ID}"
# Check whether we need to do something
read allow_lun_scan < /sys/module/zfcp/parameters/allow_lun_scan
if [ "$allow_lun_scan" = "Y" ] ; then
for host in ${_zfcp_dir}/host* ; do
[ -d $host ] || continue
hba_num=${host##*host}
done
# Automatic LUN scan is only possible on NPIV ports
read port_type < /sys/class/fc_host/host${hba_num}/port_type
if [ "$port_type" = "NPIV VPORT" ] ; then
exit 10;
fi
fi
else
echo "0" > ${_zfcp_dir}/online
# Re-read to check whether we have succeeded
_ccw_dev_status=$(cat $_zfcp_dir/online)
if [ "$_ccw_dev_status" -ne "$ONLINE" ]; then
mesg "Could not change status of device ${CCW_CHAN_ID} to $ONLINE"
exit 5
fi
echo "${CCW_CHAN_ID}" > /sys/bus/ccw/drivers/zfcp/unbind
echo "${CCW_CHAN_ID}" > /sys/bus/ccw/drivers/zfcp/bind
remove_channel_for_cio "${CCW_CHAN_ID}"
debug_mesg "zFCP adapter at ${CCW_CHAN_ID} deactivated"
fi
# EOF

91
zfcp_host_configure.8 Normal file
View File

@ -0,0 +1,91 @@
.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 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
.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-zfcp-<ccwid>.rules
.RS
This file provides the udev rules necessary to activate a specific zFCP adapter and the LUNs associated with it. Rules relating to the LUNs are added by the zfcp_disk_configure(8) script.
.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 CCW device specified
.RS
This message should never be seen, since the script checks to make sure there are exactly two parameters specified. I.e., it is a sanity check. If it is seen, please open a bug report. Return code 1 is set.
.RE
.IP
.B Invalid device status $ONLINE
.RS
A value other than 0 or 1 was specified for the second parameter, online. Return code 2 is set.
.RE
.IP
.B No device ${CCW_CHAN_ID}
.RS
If 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 Could not load module ${MODULE}
.RS
The zfcp.ko module failed to load. Try "dmesg" to see if there is any indication why. Return code 4 is set.
.RE
.IP
.B Could not activate adapter, status $wwpn_status
.RS
An attempt was made to bring the adapter online, which failed. The $wwpn_status value comes from /sys/bus/ccw/devices/$CCW_CHAN_ID/status. The adapter is explicitly set offline. Return code 5 is set.
.RE
.IP
.B Could not change status of device ${CCW_CHAN_ID} to 0
.RS
An attempt was made to take the adapter offline, which failed. Return code 5 is set.
.RE
If environment variable DEBUG is set to "yes," the following messages may be issued on stdout:
.IP
.B zFCP adapter ${CCW_CHAN_ID} already in status ${ONLINE}
.RS
An attempt was made to bring the adapter online when it was already online, or take it offline when it was already offline.
.RE
.IP
.B Configuring device ${CCW_CHAN_ID}
.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 zFCP adapter at ${CCW_CHAN_ID} deactivated
.RS
Another bit of verbosity, which means that the adapter was taken offline and the udev rules deleted.
.RE
.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)

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

501
zpxe.rexx Normal file
View File

@ -0,0 +1,501 @@
/* 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, 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
/* 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.
*/
say
say 'Enter a non-blank character and ENTER (or two ENTERs) within 10',
'seconds to interrupt zPXE.'
ADDRESS CMS 'WAKEUP +00:10 (CONS'
/* Check for the interrupt code */
if rc = 6 then do
say 'Interrupt received: exiting to CMS...'
pull /* Clear the stack */
exit
end
/* Was this script invoked with "debug" as one of the parameters? */
nodebug=1
if arg() then do
parse upper arg uparg
if index(uparg,'DEBUG') <> 0 then do
trace i
nodebug=0
end
else do /* This is a do/end in case we want to add to it later */
trace e
end
end
/* Set some defaults */
userid=''
server=''
iplDisk=''
server_def = 'internal.tftp.server' /* define default TFTP server */
iplDisk_def = '150' /* define default IPL DASD */
profilelist = 'PROFILE LIST T' /* VDISK will be defined as T later */
profiledetail = 'PROFILE DETAIL T'
zpxeparm = 'ZPXE PARM T'
zpxeconf = 'ZPXE CONF T'
config = 'ZPXE CONF A'
/* 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 nodebug 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 (VDISK) 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 nodebug then trace off
'CP DETACH FFFF' /* detach ffff if present */
if nodebug then trace e
else trace i
'CP SET EMSG ON'
'CP DEFINE VFB-512 AS FFFF BLK 144000' /* 512 byte block size ~70 MB */
queue '1'
queue 'tmpdsk'
if nodebug then /* If debug was not specified, then */
ADDRESS CMS 'set cmstype ht' /* suppress format output */
ADDRESS CMS 'format ffff t' /* format VDISK as file mode t */
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.t'
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 t (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 */
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 t (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.t'
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.t'
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.t'
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 t (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.t'
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.t'
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.t'
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 nodebug 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 nodebug 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.t' octet
if CheckDownload(kernelpath kernel img t) <> 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.t' octet
if CheckDownload(initrdpath initrd img t) <> 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 T | fblock 80 00 | > KERNEL IMG T'
ADDRESS CMS 'pipe < INITRD IMG T | fblock 80 00 | > INITRD IMG T'
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 t ( noheader' /* punch kernel */
ADDRESS CMS 'punch zpxe parm t ( noheader' /* punch PARM file */
ADDRESS CMS 'punch initrd img t ( noheader' /* punch initrd */
ADDRESS CMS 'release t (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 */