| #!/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 |
| |
| [ -x "$(which scstadmin)" ] || exit 5 |
| |
| 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 "/var/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 qla2xxx_scst qla2x00tgt \ |
| 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 |
| for m in $SCST_MODULES; do |
| if [ "$m" = "ocs_fc_scst" ]; then |
| for i in $(ls /sys/kernel/scst_tgt/targets/ocs_xe201/53:8a:95:f2:26*/enabled); do echo 1 > $i; done |
| for h in $(ls /sys/class/fc_host/); do echo "1" > /sys/class/fc_host/$h/issue_lip; done |
| fi |
| done |
| 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 /var/run/ pid file exists |
| # 2 - service dead, but /var/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 |