#! /bin/sh
# chkconfig: 2345 83 20
# description: iSCSI daemon

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

# where to make a tree of device name dirs and symlinks.  unset to disable
LINKDIR=/dev/iscsi
DIR_MODE=755

# 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

case $1 in
 start)
        # Do sanity checks before we start..
        if [ ! -f /etc/iscsi.conf ]; then
                echo "Could not find /etc/iscsi.conf!"
                exit 1
        elif [ -s $PIDFILE ] && kill -0 `head -1 $PIDFILE` >/dev/null ; then
                echo "iSCSI daemon already running"
                exit 1
        fi

        if [ ! -f /etc/initiatorname.iscsi ] ; then
            echo "InitiatorName file /etc/initiatorname.iscsi is missing!"
            exit 1
        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
            echo "" > /var/log/iscsi.log
        fi

        # see if we need to generate a unique iSCSI InitiatorName
        if grep -q "^GenerateName=yes" /etc/initiatorname.iscsi ; then
            echo "Generating a unique iSCSI InitiatorName" >> /var/log/iscsi.log
	    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=%s\n" `$BASEDIR/sbin/iscsi-iname` >> /etc/initiatorname.iscsi
	    chmod 600 /etc/initiatorname.iscsi
        fi

        # 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

	# 2.4 kernels don't use the net/core values for TCP anymore
        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"

	# the install script tells us when we need to unload an old module,
	# so that 'make install; rc.iscsi restart' does what people expect.
	if [ -d /tmp -a -e /tmp/.iscsi.unload.module ] ; then
	    rmmod iscsi_mod > /dev/null 2>&1
	    rm -f /tmp/.iscsi.unload.module
        fi

        if ! modprobe iscsi_mod >> /var/log/iscsi.log 2>&1; then
            echo
            echo "Couldn't load module iscsi_mod"
            echo "See error log in /var/log/iscsi.log"
            exit 1
        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 [ -e /proc/scsi/scsi ] ; then
		# log SCSI error handling
#		echo "scsi log scan 5" > /proc/scsi/scsi
		echo "scsi log timeout 3" > /proc/scsi/scsi
		echo "scsi log error 5" > /proc/scsi/scsi
	    fi
	    if [ -e /proc/sys/kernel/sysrq ] ; then
		# enable magic SysRq
		echo "1" > /proc/sys/kernel/sysrq
	    fi	
	    if [ -d /proc/scsi/iscsi ] ; then
		# turn on some useful kernel module debug messages by default
		for hba in /proc/scsi/iscsi/* ; do
		    echo "log sense always" > $hba
#		    echo "log login on" > $hba
		    echo "log init on" > $hba
#		    echo "log queue on" > $hba
#		    echo "log flow on" > $hba
		    echo "log eh on" > $hba
#		    echo "log alloc on" > $hba
		done
            fi
	    if [ $LINKDIR ] ; then
		# clear out any subdirs that may have been left by a system crash
		for dir in $LINKDIR/* ; do
		    if echo "$dir" | egrep -q "^$LINKDIR/bus[0-9]+$" && [ -d $dir ] ; then
			rm -rf -- $dir
		    fi
		done
		iscsid -d -l $LINKDIR -m $DIR_MODE
            else
		iscsid -d
            fi
        else
	    if [ $LINKDIR ] ; then
		# clear out any subdirs that may have been left by a system crash
		for dir in $LINKDIR/* ; do
		    if echo "$dir" | egrep -q "^$LINKDIR/bus[0-9]+$" && [ -d $dir ] ; then
			rm -rf -- $dir
		    fi
		done
		iscsid -l $LINKDIR -m $DIR_MODE
            else
		iscsid
            fi
        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

        echo ""

        ;;
 debug)
        DEBUG_ISCSI=1
        export DEBUG_ISCSI
        $0 start
        ;;
 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 [ -d /proc/scsi/iscsi ] ; then
	    echo -n " iscsi"
	    for hba in /proc/scsi/iscsi/* ; do
		echo "shutdown" > $hba
	    done
	fi

	# the install script tells us when we need to unload an old module,
	# so that 'make install; rc.iscsi start' does what people expect.
	if [ -d /tmp -a -e /tmp/.iscsi.unload.module ] ; then
	    rmmod iscsi_mod > /dev/null 2>&1
	    rm -f /tmp/.iscsi.unload.module
        fi

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

        echo
        ;;
 restart)
        $0 stop
        $0 start
        ;;
 redebug)
        $0 stop
        $0 debug
        ;;
 probe)
	# tell the daemon to reprobe LUNs
        if [ -s $PIDFILE -a `head -1 $PIDFILE` -gt 1 ] ; then
	    kill -USR1 `head -1 $PIDFILE` >/dev/null 
        fi
	;;
 *)
        echo "Unknown request $1"
        ;;
esac

exit 0
