#! /bin/sh

# For SuSE, the following information is read by "insserv" program and the
# start/stoplinks are installed at appropriate runlevels.
# The network interface and logger has to be up for starting iscsi service
### BEGIN INIT INFO
# Provides: iscsi
# Required-Start: $network $syslog
# Required-Stop:  $network $syslog
# Default-Start:  2 3 5
# Default-Stop:   0 1 6
# Description:    Start iSCSI to allow access to remote SCSI devices
### END INIT INFO

BASEDIR=/
PIDFILE=/var/run/iscsid.pid

# Source SuSE config
. /etc/rc.status

# Increase the maximum TCP window size in Linux (well, socket memory, which is related) to this number
TCP_WINDOW_SIZE=1048576

PATH="$BASEDIR/sbin:$BASEDIR/bin:/sbin:/bin:/usr/sbin:/usr/bin:$PATH"
export PATH

test -d $BASEDIR || exit 0

rc_reset
for configfile in /etc/iscsi.conf /etc/initiatorname.iscsi; do
	if [ ! -f ${configfile} ]; then
		echo -n "iSCSI configuration file, ${configfile} is missing. "
			rc_status -s
			rc_failed 6
			rc_exit
	fi
done

case $1 in
 start)
        # Do sanity checks before we start..
        if [ -s $PIDFILE ] && kill -0 `head -1 $PIDFILE` >/dev/null ; then
				echo -n "iSCSI daemon already running "
				rc_failed
				rc_status -v
				rc_exit
        fi

        grep -Eq '^[^#]' /etc/iscsi.conf
        if [ $? -ne 0 ] ; then
            echo "Error: Configuration file, /etc/iscsi.conf is empty, unable to start the driver"
				rc_status -s
				rc_failed 6
				rc_exit
        fi

	if [ ! -f /var/lib/iscsi/bindings ] ; then
	    if [ -e /etc/iscsi.bindings ] ; then
		echo
		echo "Changing the name and location of /etc/iscsi.bindings file to /var/lib/iscsi/bindings"
		if [ ! -d /var/lib/iscsi ] ; then
			mkdir -p /var/lib/iscsi
		fi
		mv /etc/iscsi.bindings /var/lib/iscsi/bindings
	    elif [ -e /var/iscsi/bindings ] ; then
		echo
		echo "Changing the name and location of /var/iscsi/bindings file to /var/lib/iscsi/bindings"
		if [ ! -d /var/lib/iscsi ] ; then
			mkdir -p /var/lib/iscsi
		fi
		mv /var/iscsi/bindings /var/lib/iscsi/bindings
            else
		echo "Name and location of the bindings file is changed to /var/lib/iscsi/bindings"
	    fi
	fi

        # see if we need to generate a unique iSCSI InitiatorName
	# this should only happen if the 
        if grep -q "^GenerateName=yes" /etc/initiatorname.iscsi ; then
	    if [ ! -x $BASEDIR/sbin/iscsi-iname ] ; then
		echo "Error: $BASEDIR/sbin/iscsi-iname does not exist, driver was not successfully installed"
		rc_failed
		ex_status -v	
		rc_exit
	    fi 
	    # Generate a unique InitiatorName and save it
	    INAME=`$BASEDIR/sbin/iscsi-iname`
	    if [ "$INAME" != "" ] ; then
		echo "## DO NOT EDIT OR REMOVE THIS FILE!" > /etc/initiatorname.iscsi
		echo "## If you remove this file, the iSCSI daemon will not start." >> /etc/initiatorname.iscsi
		echo "## If you change the InitiatorName, existing access control lists" >> /etc/initiatorname.iscsi
		echo "## may reject this initiator.  The InitiatorName must be unique">> /etc/initiatorname.iscsi
		echo "## for each iSCSI initiator.  Do NOT duplicate iSCSI InitiatorNames." >> /etc/initiatorname.iscsi
		printf "InitiatorName=$INAME\n"  >> /etc/initiatorname.iscsi
		chmod 600 /etc/initiatorname.iscsi
	    else
		echo "Error: failed to generate an iSCSI InitiatorName, driver cannot start."
		echo
		rc_failed
		rc_status -v
		rc_exit
	    fi
        fi

	# make sure there is a valid InitiatorName for the driver
        if ! grep -q "^InitiatorName=[^ \t\n]" /etc/initiatorname.iscsi ; then
	    echo
	    echo "Error: /etc/initiatorname.iscsi does not contain a valid InitiatorName."
	    echo "The iSCSI driver has not been correctly installed and cannot start."
	    echo
	rc_failed
	rc_status -v
	rc_exit
	fi

	# Check and fill up iSCSI specific entry for device creation in
	# /etc/udev/udev.rules if it does not exist already

	#
	# First, make sure iscsi_control.agent points to generic hotplug agent
	#
	if [ ! -f /etc/hotplug/iscsi_control.agent ]; then
	    ln -s /etc/hotplug/generic_udev.agent /etc/hotplug/iscsi_control.agent
	fi

        # cycle the old log, since we can't guarantee anything is managing
        # it, and in any case it's now only used for debugging info.
        if [ -e /var/log/iscsi.log ] ; then
            rm -f /var/log/iscsi.log.old
            mv /var/log/iscsi.log /var/log/iscsi.log.old
        fi
        echo "" > /var/log/iscsi.log
        chmod 0600 /var/log/iscsi.log

        # Increase the maximum TCP window size to something that will give reasonable 
        # performance for storage networking.  Use at least a 1 MB max.
        # This only works if we have /proc, but the daemon assumes that anyway,
        # so there's no point trying to use sysctl.
        if [ -e /proc/sys/net/core/rmem_max ] ; then
            RMEM_MAX=`cat /proc/sys/net/core/rmem_max`
            if [ $RMEM_MAX -lt $TCP_WINDOW_SIZE ] ; then
                echo "$TCP_WINDOW_SIZE" > /proc/sys/net/core/rmem_max
            fi
        fi

        if [ -e /proc/sys/net/core/wmem_max ] ; then
            WMEM_MAX=`cat /proc/sys/net/core/wmem_max`
            if [ $WMEM_MAX -lt $TCP_WINDOW_SIZE ] ; then
                echo "$TCP_WINDOW_SIZE" > /proc/sys/net/core/wmem_max
            fi
        fi

        if [ -e /proc/sys/net/ipv4/tcp_rmem ] ; then
	    max=`awk '{print $3}' /proc/sys/net/ipv4/tcp_rmem`
	    if [ $max -lt $TCP_WINDOW_SIZE ] ; then
		min=`awk '{print $1}' /proc/sys/net/ipv4/tcp_rmem`
		default=`awk '{print $2}' /proc/sys/net/ipv4/tcp_rmem`
		echo "$min $default $TCP_WINDOW_SIZE" > /proc/sys/net/ipv4/tcp_rmem
            fi
        fi

        if [ -e /proc/sys/net/ipv4/tcp_wmem ] ; then
	    max=`awk '{print $3}' /proc/sys/net/ipv4/tcp_wmem`
	    if [ $max -lt $TCP_WINDOW_SIZE ] ; then
		min=`awk '{print $1}' /proc/sys/net/ipv4/tcp_wmem`
		default=`awk '{print $2}' /proc/sys/net/ipv4/tcp_wmem`
		echo "$min $default $TCP_WINDOW_SIZE" > /proc/sys/net/ipv4/tcp_wmem
            fi
        fi

        # start
        echo -n "Starting iSCSI: iscsi"

	KD=/lib/modules/`uname -r`/kernel/drivers/scsi/iscsi
	EM=/lib/modules/`uname -r`/extra/iscsi.ko	#this will be removed after we provide the kernel patch

	modprobe -r iscsi >/dev/null 2>&1
	if [ -d $KD ] ; then
		/sbin/modprobe iscsi
	elif [ -f $EM ] ; then
		/sbin/modprobe iscsi
	fi

	# By default, we try to load the scsi disk driver module.
	# If SCSI support is in modules, sd_mod won't get loaded
	# until after a /dev/sd* device is opened.  This means no 
	# messages about disks will be logged until a disk device 
	# is opened.  Worse, mounting by label won't work, since
	# it relies on /proc/partitions, which won't get updated
	# until the SCSI disk driver is loaded, creating a circular
	# dependency.  To work around these problems, we try to load 
	# the disk driver here.  If you're not using SCSI disks, 
	# you can comment this out.
	modprobe sd_mod > /dev/null 2>&1

        echo -n " iscsid"

	if [ "$DEBUG_ISCSI" ] ; then
	    if [ -d /sys/class/scsi_host/iscsi ] ; then
		# turn on some useful kernel module debug messages by default
		if [ -f /sys/class/scsi_host/iscsi/log ] ; then
			echo "sense always" > /sys/class/scsi_host/iscsi/log
#			echo "login on" > /sys/class/scsi_host/iscsi/log
			echo "init on" > /sys/class/scsi_host/iscsi/log
#			echo "queue on" > /sys/class/scsi_host/iscsi/log
#			echo "flow on" > /sys/class/scsi_host/iscsi/log
			echo "retry on" > /sys/class/scsi_host/iscsi/log
		        echo "eh on" > /sys/class/scsi_host/iscsi/log
#			echo "alloc on" > /sys/class/scsi_host/iscsi/log
		fi
	    fi
            iscsid -d $DEBUG_ISCSI
        else
		iscsid
        fi

	# Make sure the K*iscsi scripts get called
	if [ -d /var/lock/subsys ] ; then 
	    touch /var/lock/subsys/iscsi 
	fi
        
        # if we have an iSCSI fstab, process it
        if [ -f /etc/fstab.iscsi ] ; then
            echo -n " fsck/mount "
            sleep 6
            iscsi-mountall
        fi

        rc_status -v

        ;;
 stop)
        echo -n "Stopping iSCSI:"

        echo -n " sync"
        sync

        # unmount all filesystems on iSCSI devices
        echo -n " umount"
        iscsi-umountall -t -k

        echo -n " sync"
        sync
        sleep 3

        if [ -f $PIDFILE ] ; then
	    echo -n " iscsid"
            kill -TERM `head -1 $PIDFILE`
	    sleep 2
            killall $BASEDIR/sbin/iscsid > /dev/null 2>&1
            killall iscsid > /dev/null 2>&1
            rm -f $PIDFILE
        fi

	# shutdown the kernel module
	if [ -f /sys/class/scsi_host/iscsi/shutdown ] ; then
                   echo  > /sys/class/scsi_host/iscsi/shutdown
	fi

	if grep -q "iscsi " /proc/modules ; then
		rmmod iscsi > /dev/null 2>&1
	fi

	if [ -e /var/lock/subsys/iscsi ] ; then
 	    rm /var/lock/subsys/iscsi
        fi

        # 
        # Remove any now stale symlinks.  We need to do this
        # since /etc/hotplug/block.agent doesn't call udev on
        # remove events.
        #
        rm -f /dev/disk/*/iscsi-*

        rc_status -v
        ;;
 restart|force-reload)
        $0 stop
        $0 start
	rc_status
        ;;
 reload)
        if [ -f $PIDFILE ] ; then
	    echo -n "Reload service iSCSI "	
            kill -HUP `head -1 $PIDFILE`
	    rc_status -v
        fi
	;;
 try-restart)
	$0 status >/dev/null && $0 restart
	rc_status
	;;
 status)
 	echo -n "Checking for service iSCSI "
        if [ -s $PIDFILE ] && kill -0 `head -1 $PIDFILE` >/dev/null ; then
            echo "iSCSI driver is loaded"
	    rc_failed 0
        else
            echo "iSCSI driver is not loaded"
	    rc_failed 3
        fi
	rc_status -v
        ;;
 debug1)
        DEBUG_ISCSI=1
        export DEBUG_ISCSI
        $0 start
        ;;
 debug2)
        DEBUG_ISCSI=2
        export DEBUG_ISCSI
        $0 start
        ;;
 debug3)
        DEBUG_ISCSI=3
        export DEBUG_ISCSI
        $0 start
        ;;
 debug4)
        DEBUG_ISCSI=4
        export DEBUG_ISCSI
        $0 start
        ;;
 debug|debug5)
        DEBUG_ISCSI=5
        export DEBUG_ISCSI
        $0 start
        ;;
 debug6)
        DEBUG_ISCSI=6
        export DEBUG_ISCSI
        $0 start
        ;;
 debug7)
        DEBUG_ISCSI=7
        export DEBUG_ISCSI
        $0 start
        ;;
 redebug1)
        $0 stop
        $0 debug1
        ;;
 redebug2)
        $0 stop
        $0 debug2
        ;;
 redebug3)
        $0 stop
        $0 debug3
        ;;
 redebug4)
        $0 stop
        $0 debug4
        ;;
 redebug|redebug5)
        $0 stop
        $0 debug5
        ;;
 redebug6)
        $0 stop
        $0 debug6
        ;;
 redebug7)
        $0 stop
        $0 debug
        ;;
 *)
        echo "Usage: /etc/init.d/iscsi { start | stop | restart | status | reload }"

        ;;
esac

rc_exit
