summaryrefslogtreecommitdiffstats
path: root/device_cio_free
diff options
context:
space:
mode:
authorDan Horák <dan@danny.cz>2010-03-25 15:44:37 +0100
committerDan Horák <dan@danny.cz>2010-03-25 15:44:37 +0100
commit6cbb2949f5b2c2d5eff141be21b53a0d3b6ca240 (patch)
tree12b2f2c2ac3db113216fb31c9a4f278781fc0b04 /device_cio_free
parentbbde12a497fdc7d425a27c9bf8fe9f36ef1fd83b (diff)
downloadutils-6cbb2949f5b2c2d5eff141be21b53a0d3b6ca240.tar.gz
utils-6cbb2949f5b2c2d5eff141be21b53a0d3b6ca240.tar.xz
utils-6cbb2949f5b2c2d5eff141be21b53a0d3b6ca240.zip
import 20100107
Diffstat (limited to 'device_cio_free')
-rw-r--r--device_cio_free129
1 files changed, 102 insertions, 27 deletions
diff --git a/device_cio_free b/device_cio_free
index 0bfaa8a..599f5ae 100644
--- a/device_cio_free
+++ b/device_cio_free
@@ -2,9 +2,9 @@
#
# Copyright 2009 Red Hat, Inc.
# License: GPLv2
-# Author: Dan Horak <dhorak@redhat.com>
+# Author: Dan Horák <dhorak@redhat.com>
#
-# unblock devices listed in various config files
+# unblock devices listed in various config files and wait until they are ready
#
# it uses dasd and zfcp config file
# config file syntax:
@@ -21,6 +21,7 @@ ZNETCONFIG=/etc/ccw.conf
BLACKLIST=/proc/cio_ignore
VERBOSE=
PATH=/bin:/usr/bin:/sbin:/usr/sbin
+ALL_DEVICES=
usage()
{
@@ -28,20 +29,62 @@ usage()
exit 1
}
+# accepts single device, comma-separated lists and dash separated ranges and their combinations
+free_device()
+{
+ local DEV
+
+ [ -z "$1" ] && return
+
+ DEV=$(echo $1 | tr "A-Z" "a-z")
+
+ [ $VERBOSE ] && echo "Freeing device(s) $DEV"
+ if [ echo "free $DEV" > $BLACKLIST 2> /dev/null ]; then
+ echo "Error: can't free device(s) $DEV"
+ else
+ if [ -z $ALL_DEVICES ]; then
+ ALL_DEVICES=$DEV
+ else
+ ALL_DEVICES="$ALL_DEVICES,$DEV"
+ fi
+ fi
+}
+
+# wait until a device appears on the ccw bus
+wait_on_device()
+{
+ local DEVICE_ONLINE DEV
+
+ [ -z "$1" ] && return
+
+ DEV=$1
+ DEVICE_ONLINE=/sys/bus/ccw/devices/$DEV/online
+
+ [ $VERBOSE ] && echo "Waiting on device $DEV"
+ [ -f "$DEVICE_ONLINE" ] && return
+
+ for t in 1 2 3 4 5
+ do
+ sleep $t
+ [ -f "$DEVICE_ONLINE" ] && return
+ done
+ echo "Error: device $DEV still not ready"
+}
+
# check how we were called
case $(basename "$0") in
"dasd_cio_free")
- CONFIG=$DASDCONFIG
+ CONFIG=$DASDCONFIG
MODE=dasd
;;
"zfcp_cio_free")
- CONFIG=$ZFCPCONFIG
- MODE=zfcp
- ;;
+ CONFIG=$ZFCPCONFIG
+ MODE=zfcp
+ ;;
"znet_cio_free")
- CONFIG=$ZNETCONFIG
- MODE=znet
- ;;
+ CONFIG=$ZNETCONFIG
+ MODE=znet
+ ;;
*)
echo "Error: unknown alias '$CMD'."
echo "Supported aliases are dasd_cio_free, zfcp_cio_free and znet_cio_free."
@@ -74,18 +117,16 @@ fi
if [ $MODE = "dasd" -o $MODE = "zfcp" ]; then
# process the config file
if [ -f "$CONFIG" ]; then
- tr "A-Z" "a-z" < $CONFIG | while read line; do
+ while read line; do
case $line in
\#*) ;;
*)
[ -z "$line" ] && continue
set $line
- DEVICE=$1
- [ $VERBOSE ] && echo "Freeing device $DEVICE"
- echo "free $DEVICE" > $BLACKLIST 2> /dev/null || echo "Error: can't free device $DEVICE"
+ free_device $1
;;
esac
- done
+ done < $CONFIG
fi
fi
@@ -93,36 +134,70 @@ if [ $MODE = "dasd" ]; then
# process the device list defined as option for the dasd module
DEVICES=$(modprobe --showconfig | grep "options[[:space:]]\+dasd_mod" | \
sed -e 's/.*[[:space:]]dasd=\([^[:space:]]*\).*/\1/' -e 's/([^)]*)//g' \
- -e 's/nopav\|nofcx\|autodetect\|probeonly//g' -e 's/,,/,/g' -e 's/^,//' -e 's/,$//' | tr "A-Z" "a-z")
+ -e 's/nopav\|nofcx\|autodetect\|probeonly//g' -e 's/,,/,/g' -e 's/^,//' -e 's/,$//')
- [ $VERBOSE ] && echo "Freeing device(s) $DEVICES"
- echo "free $DEVICES" > $BLACKLIST 2> /dev/null || echo "Error: can't free device(s) $DEVICES"
+ free_device $DEVICES
fi
if [ $MODE = "znet" ]; then
# process the config file
if [ -f "$CONFIG" ]; then
- tr "A-Z" "a-z" < $CONFIG | while read line; do
+ while read line; do
case $line in
\#*) ;;
*)
[ -z "$line" ] && continue
# grep 2 or 3 channels from beginning of each line
- DEVICES=$(echo $line | egrep -o "^([0-9]\.[0-9]\.[a-f0-9]+,){1,2}([0-9]\.[0-9]\.[a-f0-9]+)")
- if [ $DEVICES ]; then
- [ $VERBOSE ] && echo "Freeing device(s) $DEVICES"
- echo "free $DEVICES" > $BLACKLIST 2> /dev/null || echo "Error: can't free device(s) $DEVICES"
- fi
+ DEVICES=$(echo $line | egrep -i -o "^([0-9]\.[0-9]\.[a-f0-9]+,){1,2}([0-9]\.[0-9]\.[a-f0-9]+)")
+ free_device $DEVICES
;;
esac
- done
+ done < $CONFIG
fi
# process channels from network interface configurations
for line in $(egrep -i -h "^[[:space:]]*SUBCHANNELS=['\"]?([0-9]\.[0-9]\.[a-f0-9]+,){1,2}([0-9]\.[0-9]\.[a-f0-9]+)['\"]?([[:space:]]+#|[[:space:]]*$)" /etc/sysconfig/network-scripts/ifcfg-* 2> /dev/null)
do
eval "$line"
- DEVICES=$(echo $SUBCHANNELS | tr "A-Z" "a-z")
- [ $VERBOSE ] && echo "Freeing device(s) $DEVICES"
- echo "free $DEVICES" > $BLACKLIST 2> /dev/null || echo "Error: can't free device(s) $DEVICES"
+ free_device $SUBCHANNELS
done
fi
+
+# wait until recently unblocked devices are ready
+# at this point we know the content of ALL_DEVICES is syntacticly correct
+IFS=","
+set $ALL_DEVICES
+while [ "$1" ]
+do
+ DEV="$1"
+ IFS="."
+
+ # get the lower bound for range or get the single device
+ LOWER=${DEV%%-*}
+ read -a L <<< "$LOWER"
+ if [ ${#L[@]} -eq 1 ]; then
+ L[2]=${L[0]}
+ L[0]=0
+ L[1]=0
+ fi
+
+ # get the upper bound for range or get the single device
+ UPPER=${DEV##*-}
+ read -a U <<< "$UPPER"
+ if [ ${#U[@]} -eq 1 ]; then
+ U[2]=${U[0]}
+ U[0]=0
+ U[1]=0
+ fi
+
+ # iterate thru all devices
+ for (( i=0x${L[0]}; i<=0x${U[0]}; i++ )); do
+ for (( j=0x${L[1]}; j<=0x${U[1]}; j++ )); do
+ for (( k=0x${L[2]}; k<=0x${U[2]}; k++ )); do
+ wait_on_device "$(printf %x.%x.%04x $i $j $k)"
+ done
+ done
+ done
+
+ # go to the next device
+ shift
+done