mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-25 07:51:28 +00:00
qla2x00tgt holds a reference on qla2xxx_scst, so it must be unloaded first. The wrong order caused a 30-second timeout on every shutdown.
398 lines
10 KiB
Bash
Executable File
398 lines
10 KiB
Bash
Executable File
#!/bin/sh
|
|
#
|
|
# A script that generates the /etc/init.d/scst script. On systems that support
|
|
# the LSB an LSB compliant init script is generated. On Gentoo systems a Gentoo
|
|
# init script is generated. And on Slackware the LSB init script is used with
|
|
# replacements for the used LSB functions.
|
|
|
|
if [ -e /etc/gentoo-release ]; then
|
|
echo "#!/sbin/runscript"
|
|
else
|
|
echo "#!/bin/sh"
|
|
fi
|
|
|
|
cat <<"EOF"
|
|
#
|
|
# Copyright (C) 2008 Mark Buechler <mark.buechler@gmail.com>
|
|
# Copyright (C) 2009-2011 Bart Van Assche <bvanassche@acm.org>
|
|
# This software is made available under the GPLv2 license.
|
|
#
|
|
# System startup script for SCST.
|
|
#
|
|
# See also:
|
|
# * http://refspecs.freestandards.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
|
|
# * http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
|
|
#
|
|
EOF
|
|
|
|
if [ ! -e /etc/gentoo-release ]; then
|
|
cat <<"EOF"
|
|
### BEGIN INIT INFO
|
|
# Provides: scst
|
|
# Required-Start: $syslog $local_fs $network
|
|
# Required-Stop: $syslog $local_fs $network
|
|
# Default-Start: 3 5
|
|
# Default-Stop: 0 1 2 4 6
|
|
# Description: SCST - A Generic SCSI Target Subsystem
|
|
### END INIT INFO
|
|
### BEGIN CHKCONFIG INFO
|
|
# chkconfig: 2345 13 87
|
|
# description: SCST - A Generic SCSI Target Subsystem
|
|
### END CHKCONFIG INFO
|
|
|
|
# Return values according to LSB for all commands except 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
|
|
#
|
|
|
|
if [ -e /lib/lsb/init-functions ]; then
|
|
# Debian, RHEL, Fedora, SLES and openSUSE.
|
|
SYSTEMD_NO_WRAP="true"
|
|
_SYSTEMCTL_SKIP_REDIRECT=1
|
|
. /lib/lsb/init-functions
|
|
else
|
|
# Slackware (Gentoo has these functions).
|
|
log_success_msg() {
|
|
echo "$@"
|
|
}
|
|
log_failure_msg() {
|
|
echo "$@"
|
|
}
|
|
fi
|
|
|
|
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin
|
|
SCST_DFLT=/etc/default/scst
|
|
|
|
if [ -f $SCST_DFLT ]; then
|
|
. $SCST_DFLT
|
|
fi
|
|
EOF
|
|
fi
|
|
|
|
cat <<"EOF"
|
|
|
|
SCST_CFG=/etc/scst.conf
|
|
|
|
show_status() {
|
|
_rc_status_ret=$?
|
|
for i; do
|
|
case "$i" in
|
|
-v)
|
|
case "${_rc_status_ret}" in
|
|
0) echo "OK";;
|
|
*) echo "Not running";;
|
|
esac
|
|
;;
|
|
esac
|
|
done
|
|
return ${_rc_status_ret}
|
|
}
|
|
|
|
if [ ! -e /lib/lsb/init-functions ]; then
|
|
# Slackware and Gentoo.
|
|
start_daemon() {
|
|
"$@" >/dev/null 2>&1 &
|
|
}
|
|
killproc() {
|
|
exe=$(basename "$1")
|
|
killall "$exe"
|
|
rm -f "/run/$exe.pid"
|
|
}
|
|
fi
|
|
|
|
# Whether or not there is a "TARGET_DRIVER iscsi" section in scst.conf.
|
|
using_iscsi() {
|
|
for m in $SCST_MODULES; do
|
|
if [ "$m" = "iscsi_scst" ]; then
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Parse scst.conf and assign the list of associated kernel modules to
|
|
# SCST_MODULES.
|
|
parse_scst_conf() {
|
|
SCST_MODULES="scst"
|
|
SCST_OPT_MODULES=""
|
|
SCST_DAEMONS=""
|
|
if [ ! -e $SCST_CFG ]; then
|
|
return 0
|
|
fi
|
|
nonblanks="[^[:blank:]]\{1,\}"
|
|
blanks="[[:blank:]]\{1,\}"
|
|
optblanks="[[:blank:]]*"
|
|
SCST_MODULES="$SCST_MODULES $(sed -n -e "s/^HANDLER$blanks\($nonblanks\)$blanks{$optblanks\$/\1/p" \
|
|
-e "s/^\[HANDLER$blanks\($nonblanks\)\]\$/\1/p" $SCST_CFG \
|
|
| while read -r h; do
|
|
case "$h" in
|
|
dev_cdrom) echo scst_cdrom;;
|
|
dev_changer) echo scst_changer;;
|
|
dev_disk*) echo scst_disk;;
|
|
dev_modisk*) echo scst_modisk;;
|
|
dev_processor) echo scst_processor;;
|
|
dev_raid) echo scst_raid;;
|
|
dev_tape*) echo scst_tape;;
|
|
dev_user) echo scst_user;;
|
|
vdisk*|vcdrom) echo scst_vdisk;;
|
|
*) echo "$h";;
|
|
esac
|
|
done | sort -u) \
|
|
$(sed -n "s/^TARGET_DRIVER$blanks\($nonblanks\)$blanks{$optblanks\$/\1/p" $SCST_CFG | while read -r d; do
|
|
case "$d" in
|
|
iscsi) echo iscsi_scst;;
|
|
qla2x00t) echo qla2x00tgt;;
|
|
copy_manager) ;;
|
|
*) echo "$d";;
|
|
esac
|
|
done | sort -u) \
|
|
$SCST_TARGET_MODULES"
|
|
if using_iscsi; then
|
|
case "$(uname -m)" in
|
|
x86_64|i686)
|
|
SCST_OPT_MODULES="crc32c-intel $SCST_OPT_MODULES";;
|
|
esac
|
|
SCST_OPT_MODULES="crc32c isert_scst $SCST_OPT_MODULES"
|
|
SCST_DAEMONS="$(which iscsi-scstd) $SCST_DAEMONS"
|
|
fi
|
|
}
|
|
|
|
# Keep trying to unload kernel module $1 for up to $2 seconds. Return true
|
|
# if and only if the kernel module was unloaded before the timeout expired.
|
|
unload_kmod() {
|
|
m="$1"
|
|
t="$2"
|
|
i=0
|
|
while [ -e "/sys/module/$m/refcnt" ] && ! modprobe -r "$m" 2>/dev/null &&
|
|
[ $i -lt "$t" ]
|
|
do
|
|
sleep 1
|
|
i=$((i+1))
|
|
done
|
|
[ ! -e "/sys/module/$m/refcnt" ]
|
|
}
|
|
|
|
# Unload SCST. parse_scst_conf must already have been invoked.
|
|
unload_scst() {
|
|
for d in $SCST_DAEMONS; do
|
|
killproc "$d"
|
|
done
|
|
|
|
# isert_scst must be unloaded before iscsi_scst. Note that unloading
|
|
# isert_scst may take a while since in certain scenarios (e.g. cable
|
|
# problem and then service stop) MADs get timed out only after about 50+
|
|
# seconds.
|
|
unload_kmod isert_scst 90 || echo "Unloading isert_scst failed"
|
|
|
|
for m in isert_scst iscsi_scst fcst ib_srpt qla2x00tgt qla2xxx_scst \
|
|
scst_local scst_disk scst_raid scst_tape scst_user scst_changer \
|
|
scst_cdrom scst_vdisk scst_modisk scst_processor scst; do
|
|
unload_kmod "$m" 30
|
|
done
|
|
reverse_list=""
|
|
for m in $SCST_MODULES; do
|
|
reverse_list="$m $reverse_list"
|
|
done
|
|
for m in $reverse_list; do
|
|
unload_kmod "$m" 30 || return 1
|
|
done
|
|
|
|
# Clear the config in case unloading failed or SCST has been built into the
|
|
# kernel
|
|
if [ -e /sys/module/scst ]; then
|
|
scstadmin -noprompt -force -clear_config >/dev/null 2>&1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
start_scst() {
|
|
if [ -e /sys/module/scst ] && [ -e /sys/module/scst/refcnt ]; then
|
|
echo Already started
|
|
return 0
|
|
fi
|
|
|
|
parse_scst_conf
|
|
|
|
for m in $SCST_OPT_MODULES; do
|
|
modprobe "$m" >/dev/null 2>&1
|
|
done
|
|
|
|
for m in $SCST_MODULES; do
|
|
if [ ! -e "/sys/module/$m" ]; then
|
|
if ! modprobe "$m"; then
|
|
echo "modprobe $m failed."
|
|
unload_scst
|
|
return 5
|
|
fi
|
|
fi
|
|
done
|
|
|
|
for d in $SCST_DAEMONS; do
|
|
options=""
|
|
if [ "$(basename "$d")" = "iscsi-scstd" ]; then
|
|
options=${ISCSID_OPTIONS}
|
|
fi
|
|
if ! start_daemon "$d" $options; then
|
|
echo "Starting $d failed"
|
|
unload_scst
|
|
return 1
|
|
fi
|
|
done
|
|
|
|
if [ -f $SCST_CFG ]; then
|
|
scstadmin -force -noprompt -clear_config >/dev/null 2>&1
|
|
tmpout=/tmp/scstadmin-output-$$
|
|
if scstadmin -config $SCST_CFG >$tmpout 2>&1; then
|
|
rm -f $tmpout
|
|
return 0
|
|
else
|
|
cat $tmpout
|
|
rm -f $tmpout
|
|
unload_scst
|
|
return 1
|
|
fi
|
|
else
|
|
echo "SCST configuration file $SCST_CFG missing"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
stop_scst() {
|
|
if ! parse_scst_conf; then
|
|
return 1
|
|
fi
|
|
|
|
unload_scst
|
|
}
|
|
|
|
scst_status() {
|
|
# Status has a slightly different meaning for the status command:
|
|
# 0 - service running
|
|
# 1 - service dead, but /run/ pid file exists
|
|
# 2 - service dead, but /run/lock/ lock file exists
|
|
# 3 - service not running
|
|
|
|
parse_scst_conf
|
|
|
|
for m in $SCST_MODULES; do
|
|
if [ ! -e "/sys/module/$m" ]; then
|
|
echo "$m: not loaded"
|
|
return 3
|
|
fi
|
|
done
|
|
|
|
for d in $SCST_DAEMONS; do
|
|
daemon_name=$(basename "${d}")
|
|
if ! pgrep "${daemon_name}" > /dev/null 2>&1; then
|
|
echo "${daemon_name}: not running"
|
|
return 3
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
EOF
|
|
|
|
if [ ! -e /etc/gentoo-release ]; then
|
|
cat <<"EOF"
|
|
rc=0
|
|
case "$1" in
|
|
start)
|
|
## Start the service.
|
|
echo -n "Loading and configuring SCST"
|
|
start_scst
|
|
rc=$?
|
|
;;
|
|
stop)
|
|
## Stop the service.
|
|
echo -n "Stopping SCST"
|
|
stop_scst
|
|
rc=$?
|
|
;;
|
|
restart)
|
|
## Stop and restart the service if the service is already running,
|
|
## otherwise start the service.
|
|
echo -n "Restarting SCST"
|
|
stop_scst && start_scst
|
|
rc=$?
|
|
;;
|
|
try-restart)
|
|
## Restart the service if the service is already running.
|
|
echo -n "Trying to restart SCST"
|
|
scst_status >/dev/null 2>&1 && stop_scst && start_scst
|
|
rc=$?
|
|
;;
|
|
reload)
|
|
## Cause the configuration of the service to be reloaded without
|
|
## actually stopping and restarting the service.
|
|
echo -n "Reloading SCST configuration"
|
|
if scstadmin -config $SCST_CFG >/dev/null 2>&1; then
|
|
rc=0
|
|
else
|
|
rc=1
|
|
fi
|
|
;;
|
|
force-reload)
|
|
## Cause the configuration to be reloaded if the service supports this,
|
|
## otherwise restart the service if it is running.
|
|
echo -n "Reloading SCST configuration"
|
|
if scstadmin -config $SCST_CFG >/dev/null 2>&1; then
|
|
rc=0
|
|
else
|
|
stop_scst && start_scst
|
|
rc=$?
|
|
fi
|
|
;;
|
|
status)
|
|
## Print the current status of the service.
|
|
echo -n "SCST status: "
|
|
scst_status >/dev/null 2>&1
|
|
show_status -v
|
|
exit $?
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload}"
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
if [ $rc = 0 ]; then
|
|
log_success_msg ""
|
|
else
|
|
log_failure_msg ""
|
|
fi
|
|
|
|
exit $rc
|
|
EOF
|
|
else
|
|
cat <<"EOF"
|
|
depend() {
|
|
need localmount
|
|
need net
|
|
}
|
|
|
|
checkconfig() {
|
|
true
|
|
}
|
|
|
|
start() {
|
|
ebegin "Starting SCST"
|
|
start_scst
|
|
eend $?
|
|
}
|
|
|
|
stop() {
|
|
ebegin "Stopping SCST"
|
|
stop_scst
|
|
eend $?
|
|
}
|
|
EOF
|
|
fi
|