From 6cbb2949f5b2c2d5eff141be21b53a0d3b6ca240 Mon Sep 17 00:00:00 2001 From: Dan Horák Date: Thu, 25 Mar 2010 15:44:37 +0100 Subject: import 20100107 --- device_cio_free | 129 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file 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 +# Author: Dan Horák # -# 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 -- cgit