aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/40-usb-blacklist.rules14
-rw-r--r--scripts/54-before-scsi-sg3_id.rules55
-rw-r--r--scripts/55-scsi-sg3_id.rules109
-rw-r--r--scripts/58-scsi-sg3_symlink.rules38
-rw-r--r--scripts/59-fc-wwpn-id.rules17
-rw-r--r--scripts/59-scsi-cciss_id.rules18
-rw-r--r--scripts/Makefile.am3
-rw-r--r--scripts/Makefile.in518
-rw-r--r--scripts/README55
-rwxr-xr-xscripts/cciss_id66
-rw-r--r--scripts/fc_wwpn_id51
-rw-r--r--scripts/lunmask.service11
-rwxr-xr-xscripts/rescan-scsi-bus.sh1436
-rwxr-xr-xscripts/scsi-enable-target-scan.sh15
-rwxr-xr-xscripts/scsi_logging_level268
-rwxr-xr-xscripts/scsi_mandat133
-rwxr-xr-xscripts/scsi_readcap57
-rwxr-xr-xscripts/scsi_ready56
-rwxr-xr-xscripts/scsi_satl134
-rwxr-xr-xscripts/scsi_start55
-rwxr-xr-xscripts/scsi_stop58
-rwxr-xr-xscripts/scsi_temperature46
22 files changed, 3213 insertions, 0 deletions
diff --git a/scripts/40-usb-blacklist.rules b/scripts/40-usb-blacklist.rules
new file mode 100644
index 00000000..66313880
--- /dev/null
+++ b/scripts/40-usb-blacklist.rules
@@ -0,0 +1,14 @@
+#
+# Blacklist specific USB devices
+#
+# don't inquire sn and di on broken devices (https://bugzilla.suse.com/show_bug.cgi?id=840054)
+
+ACTION!="add|change", GOTO="usb_blacklist_end"
+KERNEL!="sd*[!0-9]|sr*", GOTO="usb_blacklist_end"
+
+# unknown device
+ATTRS{idVendor}=="0aec", ATTRS{idProduct}=="3260", ENV{ID_SCSI_INQUIRY}="1"
+# Sony/JMicron port replicator
+ATTRS{idVendor}=="054c", ATTRS{idProduct}=="06a0", ENV{ID_SCSI_INQUIRY}="1"
+
+LABEL="usb_blacklist_end"
diff --git a/scripts/54-before-scsi-sg3_id.rules b/scripts/54-before-scsi-sg3_id.rules
new file mode 100644
index 00000000..bb36650a
--- /dev/null
+++ b/scripts/54-before-scsi-sg3_id.rules
@@ -0,0 +1,55 @@
+# do not edit this file, it will be overwritten on update
+
+# persistent storage links: /dev/disk/{by-id,by-path}
+# scheme based on "Linux persistent device names", 2004, Hannes Reinecke <hare@suse.de>
+
+# This file contains rules for setting udev environment variables based on
+# hardware properties (serial numbers etc), which can be obtained without
+# actually reading from the device.
+#
+# Hopefully this will be integrated into systemd/udev soon (as 54-storage-hardware.rules).
+# Until then, we ship it here in sg3-utils.
+# It's important that rules dealing with low-level hardware attributes run
+# before the generic SCSI rules in 55-scsi-sg3_utils.rules.
+
+ACTION=="remove", GOTO="storage_hardware_end"
+SUBSYSTEM!="block", GOTO="block_storage_end"
+KERNEL!="sd*|sr*|cciss*", GOTO="block_storage_end"
+
+# ignore partitions that span the entire disk
+TEST=="whole_disk", GOTO="block_storage_end"
+
+# for partitions import parent information
+ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}!="?*", IMPORT{parent}="ID_*"
+
+# ATA
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", IMPORT{program}="ata_id --export $devnode"
+
+# ATAPI devices (SPC-3 or later)
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="scsi", ATTRS{type}=="5", ATTRS{scsi_level}=="[6-9]*", IMPORT{program}="ata_id --export $devnode"
+
+# Run ata_id on non-removable USB Mass Storage (SATA/PATA disks in enclosures)
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", ATTR{removable}=="0", SUBSYSTEMS=="usb", IMPORT{program}="ata_id --export $devnode"
+
+# Fall back usb_id for USB devices
+KERNEL=="sd*[!0-9]|sr*", ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", IMPORT{builtin}="usb_id"
+
+# FireWire
+ENV{ID_IEEE1394}!="?*", KERNEL=="sd*|sr*", ATTRS{ieee1394_id}=="?*", ENV{ID_IEEE1394}="$attr{ieee1394_id}"
+
+# by-path
+ENV{ID_PATH}!="?*", ENV{DEVTYPE}=="disk", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id"
+
+LABEL="block_storage_end"
+
+# SCSI tape devices
+SUBSYSTEM!="scsi_tape", GOTO="storage_hardware_end"
+KERNEL!="st*[0-9]|nst*[0-9]", GOTO="storage_hardware_end"
+
+ENV{ID_SERIAL}!="?*", ATTRS{ieee1394_id}=="?*", ENV{ID_SERIAL}="$attr{ieee1394_id}", ENV{ID_BUS}="ieee1394"
+ENV{ID_SERIAL}!="?*", SUBSYSTEMS=="usb", ATTRS{serial}=="?*", IMPORT{builtin}="usb_id"
+
+# by-path
+ENV{ID_PATH}!="?*", IMPORT{builtin}="path_id"
+
+LABEL="storage_hardware_end"
diff --git a/scripts/55-scsi-sg3_id.rules b/scripts/55-scsi-sg3_id.rules
new file mode 100644
index 00000000..453210bd
--- /dev/null
+++ b/scripts/55-scsi-sg3_id.rules
@@ -0,0 +1,109 @@
+# SCSI-ID mappings for sg3_utils
+
+ACTION=="remove", GOTO="sg3_utils_id_end"
+
+SUBSYSTEM=="block", GOTO="block_dev"
+
+# SCSI devices other than "block"
+# This code used to live in 60-persistent-storage-tape.rules.
+
+# type 8 devices are "Medium Changers"
+SUBSYSTEM=="scsi_generic", KERNEL=="sg*[0-9]", ATTRS{type}=="8", \
+ GOTO="scsi_inquiry"
+SUBSYSTEM=="scsi_changer", KERNEL=="sch*[0-9]", ATTRS{type}=="8", \
+ ENV{.INQUIRY_DEV}="$root/bsg/$id", GOTO="scsi_inquiry"
+
+# tapes need to be accessed through their bsg device
+KERNEL=="st*[0-9]|nst*[0-9]", SUBSYSTEMS=="scsi", KERNELS=="[0-9]*:*[0-9]", \
+ ENV{.INQUIRY_DEV}="$root/bsg/$id", GOTO="scsi_inquiry"
+
+GOTO="sg3_utils_id_end"
+
+LABEL="block_dev"
+
+# Import values for partitions
+ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_SCSI", IMPORT{parent}="SCSI_*"
+ENV{DEVTYPE}=="partition", ENV{ID_SCSI}=="1", GOTO="compat"
+
+# Handle non-SCSI devices that implement SCSI inquiry
+KERNEL=="cciss*", ENV{DEVTYPE}=="disk", GOTO="sg_inquiry"
+
+# Ignore everything else except sd/sr
+KERNEL!="sd*[!0-9]|sr*", GOTO="sg3_utils_id_end"
+
+# SCSI INQUIRY values
+# If the 'inquiry' sysfs attribute is present the kernel will already
+# have scanned for VPD pages, so if the vpd page attribute is not
+# present it is not supported (or deemed unsafe to access).
+# Hence we can skip the call to sg_inq and avoid I/O altogether.
+# Set 'ID_SCSI_INQUIRY=0' in an earlier udev rule if the kernel
+# fails to scan VPD pages correctly; the rules will then fall
+# back to calling sg_vpd directly.
+LABEL="scsi_inquiry"
+ENV{ID_SCSI_INQUIRY}=="0", GOTO="sg_inquiry"
+
+# "inquiry" is an attribute of the scsi_device in sysfs,
+# we obtain it by using $id after an ATTRS match.
+SUBSYSTEMS=="scsi", ATTRS{inquiry}=="*", KERNELS=="[0-9]*:*[0-9]", \
+ ENV{.SYSFS_PATH}="$sys/class/scsi_device/$id/device"
+ENV{.SYSFS_PATH}=="", GOTO="sg_inquiry"
+
+IMPORT{program}="/usr/bin/sg_inq --export --inhex=$env{.SYSFS_PATH}/inquiry --raw", \
+ ENV{ID_SCSI}="1", ENV{ID_SCSI_INQUIRY}="1"
+# If inquiry sysfs attribute reading it failed, fallback to sg
+ENV{ID_SCSI}!="1", GOTO="sg_inquiry"
+# Read VPD pages 80 (sn) and 83 (di)
+IMPORT{program}="/usr/bin/sg_inq --export --inhex=$env{.SYSFS_PATH}/vpd_pg80 --raw"
+IMPORT{program}="/usr/bin/sg_inq --export --inhex=$env{.SYSFS_PATH}/vpd_pg83 --raw"
+GOTO="compat"
+
+LABEL="sg_inquiry"
+# Handle devices that have no inquiry attributes in sysfs
+ENV{.INQUIRY_DEV}=="", ENV{.INQUIRY_DEV}="$tempnode"
+
+IMPORT{program}="/usr/bin/sg_inq --export $env{.INQUIRY_DEV}", ENV{ID_SCSI}="1"
+# Give up if this fails, too
+ENV{ID_SCSI}!="1", GOTO="sg3_utils_id_end"
+IMPORT{program}="/usr/bin/sg_inq --export --page=sn $env{.INQUIRY_DEV}"
+IMPORT{program}="/usr/bin/sg_inq --export --page=di $env{.INQUIRY_DEV}"
+
+LABEL="compat"
+
+# scsi_id compat mappings
+ENV{ID_VENDOR}!="?*", ENV{SCSI_VENDOR}=="?*", ENV{ID_VENDOR}="$env{SCSI_VENDOR}"
+ENV{ID_VENDOR_ENC}!="?*", ENV{SCSI_VENDOR_ENC}=="?*", ENV{ID_VENDOR_ENC}="$env{SCSI_VENDOR_ENC}"
+ENV{ID_MODEL}!="?*", ENV{SCSI_MODEL}=="?*", ENV{ID_MODEL}="$env{SCSI_MODEL}"
+ENV{ID_MODEL_ENC}!="?*", ENV{SCSI_MODEL_ENC}=="?*", ENV{ID_MODEL_ENC}="$env{SCSI_MODEL_ENC}"
+ENV{ID_REVISION}!="?*", ENV{SCSI_REVISION}=="?*", ENV{ID_REVISION}="$env{SCSI_REVISION}"
+ENV{ID_TYPE}!="?*", ENV{SCSI_TYPE}=="?*", ENV{ID_TYPE}="$env{SCSI_TYPE}"
+ENV{ID_TARGET_PORT}!="?*", ENV{SCSI_IDENT_PORT_TARGET_PORT_GROUP}=="?*", \
+ PROGRAM="/bin/sh -c 'echo $env{SCSI_IDENT_PORT_TARGET_PORT_GROUP} | /bin/sed s/^0x//'", \
+ ENV{ID_TARGET_PORT}="$result"
+
+# ID_WWN compat mapping
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA_REG}"
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA_EXT}"
+ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{ID_WWN_WITH_EXTENSION}!="?*", ENV{ID_WWN_WITH_EXTENSION}="0x$env{SCSI_IDENT_LUN_NAA_LOCAL}"
+# ID_WWN has max 16 characters
+ENV{ID_WWN_WITH_EXTENSION}=="?*", ENV{ID_WWN}!="?*", \
+ PROGRAM="/bin/sh -c 'echo $env{ID_WWN_WITH_EXTENSION} | /bin/sed s/^\\\(0x.\\\{1,16\\\}\\\).*/\\1/'", \
+ ENV{ID_WWN}="$result"
+
+# ata_id compatibility
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_ATA}=="?*", ENV{ID_BUS}="ata", ENV{ID_ATA}="1", ENV{ID_SERIAL}="$env{SCSI_IDENT_LUN_ATA}"
+ENV{ID_SERIAL_SHORT}!="?*", ENV{SCSI_VENDOR}=="ATA", ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_VENDOR}"
+# Compat ID_SERIAL setting
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_REGEXT}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_REG}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_REG}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_EXT}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_EXT}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="2$env{SCSI_IDENT_LUN_EUI64}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_EUI64}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAME}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="8$env{SCSI_IDENT_LUN_NAME}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAME}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_T10}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="1$env{SCSI_IDENT_LUN_T10}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_T10}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="3$env{SCSI_IDENT_LUN_NAA_LOCAL}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_NAA_LOCAL}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="0$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_LUN_VENDOR}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_LUN_VENDOR}"
+ENV{ID_SERIAL}!="?*", ENV{SCSI_IDENT_SERIAL}=="?*", ENV{ID_BUS}="scsi", ENV{ID_SERIAL}="S$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_SERIAL}", ENV{ID_SERIAL_SHORT}="$env{SCSI_IDENT_SERIAL}"
+
+# Compat ID_SCSI_SERIAL setting
+ENV{ID_SCSI_SERIAL}!="?*", ENV{SCSI_IDENT_SERIAL}=="?*", ENV{ID_SCSI_SERIAL}="$env{SCSI_IDENT_SERIAL}"
+LABEL="sg3_utils_id_end"
diff --git a/scripts/58-scsi-sg3_symlink.rules b/scripts/58-scsi-sg3_symlink.rules
new file mode 100644
index 00000000..fe6b0000
--- /dev/null
+++ b/scripts/58-scsi-sg3_symlink.rules
@@ -0,0 +1,38 @@
+# SCSI-ID symlinks for sg3_utils
+
+ACTION=="remove", GOTO="sg3_utils_symlink_end"
+
+SUBSYSTEM!="block", GOTO="sg3_utils_symlink_end"
+ENV{UDEV_DISABLE_PERSISTENT_STORAGE_RULES_FLAG}=="1", GOTO="sg3_utils_symlink_end"
+
+# Select which identifier to use per default
+# 0: vpd page 0x80 identifier
+ENV{SCSI_IDENT_SERIAL}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-S$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_SERIAL}"
+ENV{SCSI_IDENT_SERIAL}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-S$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_SERIAL}-part%n"
+# NAA identifier (prefix 3)
+# 1: IEEE Registered Extended first
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REGEXT}"
+ENV{SCSI_IDENT_LUN_NAA_REGEXT}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REGEXT}-part%n"
+# 2: IEEE Registered
+ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REG}"
+ENV{SCSI_IDENT_LUN_NAA_REG}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_REG}-part%n"
+# 3: IEEE Extended
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_EXT}"
+ENV{SCSI_IDENT_LUN_NAA_EXT}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_EXT}-part%n"
+# 4: EUI-64 identifier (prefix 2)
+ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-2$env{SCSI_IDENT_LUN_EUI64}"
+ENV{SCSI_IDENT_LUN_EUI64}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-2$env{SCSI_IDENT_LUN_EUI64}-part%n"
+# 5: SCSI name identifier (prefix 8)
+ENV{SCSI_IDENT_LUN_NAME}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-8$env{SCSI_IDENT_LUN_NAME}"
+ENV{SCSI_IDENT_LUN_NAME}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-8$env{SCSI_IDENT_LUN_NAME}-part%n"
+# 6: T10 Vendor identifier (prefix 1)
+ENV{SCSI_IDENT_LUN_T10}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-1$env{SCSI_IDENT_LUN_T10}"
+ENV{SCSI_IDENT_LUN_T10}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-1$env{SCSI_IDENT_LUN_T10}-part%n"
+# 7: IEEE Locally assigned
+ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_LOCAL}"
+ENV{SCSI_IDENT_LUN_NAA_LOCAL}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-3$env{SCSI_IDENT_LUN_NAA_LOCAL}-part%n"
+# 8: Vendor-specific identifier (prefix 0)
+ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-id/scsi-0$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_LUN_VENDOR}"
+ENV{SCSI_IDENT_LUN_VENDOR}=="?*", ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-id/scsi-0$env{SCSI_VENDOR}_$env{SCSI_MODEL}_$env{SCSI_IDENT_LUN_VENDOR}-part%n"
+
+LABEL="sg3_utils_symlink_end"
diff --git a/scripts/59-fc-wwpn-id.rules b/scripts/59-fc-wwpn-id.rules
new file mode 100644
index 00000000..5ad0a5c8
--- /dev/null
+++ b/scripts/59-fc-wwpn-id.rules
@@ -0,0 +1,17 @@
+#
+# FC WWPN-based by-path links
+#
+
+ACTION!="add|change", GOTO="fc_wwpn_end"
+KERNEL!="sd*", GOTO="fc_wwpn_end"
+
+ENV{DEVTYPE}=="disk", IMPORT{program}="fc_wwpn_id %p"
+ENV{DEVTYPE}=="partition", IMPORT{parent}="FC_*"
+ENV{FC_TARGET_WWPN}!="?*", GOTO="fc_wwpn_end"
+ENV{FC_INITIATOR_WWPN}!="?*", GOTO="fc_wwpn_end"
+ENV{FC_TARGET_LUN}!="?*", GOTO="fc_wwpn_end"
+
+ENV{DEVTYPE}=="disk", SYMLINK+="disk/by-path/fc-$env{FC_INITIATOR_WWPN}-$env{FC_TARGET_WWPN}-lun-$env{FC_TARGET_LUN}"
+ENV{DEVTYPE}=="partition", SYMLINK+="disk/by-path/fc-$env{FC_INITIATOR_WWPN}-$env{FC_TARGET_WWPN}-lun-$env{FC_TARGET_LUN}-part%n"
+
+LABEL="fc_wwpn_end"
diff --git a/scripts/59-scsi-cciss_id.rules b/scripts/59-scsi-cciss_id.rules
new file mode 100644
index 00000000..4eb4561e
--- /dev/null
+++ b/scripts/59-scsi-cciss_id.rules
@@ -0,0 +1,18 @@
+# cciss compat rules
+
+ACTION!="add|change", GOTO="cciss_compat_end"
+KERNEL!="sd*", GOTO="cciss_compat_end"
+ENV{ID_VENDOR}!="HP", ENV{ID_VENDOR}!="COMPAQ", GOTO="cciss_compat_end"
+ENV{ID_MODEL}!="LOGICAL_VOLUME", GOTO="cciss_compat_end"
+
+ENV{DEVTYPE}=="disk", DRIVERS=="hpsa", IMPORT{program}="cciss_id %p"
+ENV{DEVTYPE}=="partition", IMPORT{parent}="ID_*"
+ENV{ID_CCISS}!="?*", GOTO="cciss_compat_end"
+
+ENV{DEVTYPE}=="disk", SYMLINK+="cciss/$env{ID_CCISS}"
+ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/cciss-$env{ID_SERIAL}"
+
+ENV{DEVTYPE}=="partition", SYMLINK+="cciss/$env{ID_CCISS}p%n"
+ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/cciss-$env{ID_SERIAL}-part%n"
+
+LABEL="cciss_compat_end"
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
new file mode 100644
index 00000000..01d44362
--- /dev/null
+++ b/scripts/Makefile.am
@@ -0,0 +1,3 @@
+dist_bin_SCRIPTS = scsi_logging_level scsi_mandat scsi_readcap scsi_ready \
+ scsi_satl scsi_start scsi_stop scsi_temperature \
+ rescan-scsi-bus.sh
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
new file mode 100644
index 00000000..21673ab2
--- /dev/null
+++ b/scripts/Makefile.in
@@ -0,0 +1,518 @@
+# Makefile.in generated by automake 1.16.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2021 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = scripts
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(dist_bin_SCRIPTS) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(bindir)"
+SCRIPTS = $(dist_bin_SCRIPTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__DIST_COMMON = $(srcdir)/Makefile.in README
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CSCOPE = @CSCOPE@
+CTAGS = @CTAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ETAGS = @ETAGS@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FILECMD = @FILECMD@
+GETOPT_O_FILES = @GETOPT_O_FILES@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_LIB = @PTHREAD_LIB@
+RANLIB = @RANLIB@
+RT_LIB = @RT_LIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+os_cflags = @os_cflags@
+os_libs = @os_libs@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+dist_bin_SCRIPTS = scsi_logging_level scsi_mandat scsi_readcap scsi_ready \
+ scsi_satl scsi_start scsi_stop scsi_temperature \
+ rescan-scsi-bus.sh
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign scripts/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign scripts/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-dist_binSCRIPTS: $(dist_bin_SCRIPTS)
+ @$(NORMAL_INSTALL)
+ @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n' \
+ -e 'h;s|.*|.|' \
+ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+ if (++n[d] == $(am__install_max)) { \
+ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+ else { print "f", d "/" $$4, $$1 } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-dist_binSCRIPTS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(dist_bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 's,.*/,,;$(transform)'`; \
+ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir)
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(SCRIPTS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-dist_binSCRIPTS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-dist_binSCRIPTS
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-dist_binSCRIPTS install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
+ uninstall-am uninstall-dist_binSCRIPTS
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/scripts/README b/scripts/README
new file mode 100644
index 00000000..72cbdcf5
--- /dev/null
+++ b/scripts/README
@@ -0,0 +1,55 @@
+ README for sg3_utils/scripts
+ ============================
+Introduction
+============
+This directory contains bash shell scripts. Most of them call one or
+more utilities from the sg3_utils package. They assume the sg3_utils
+package utilities are on the PATH of the user.
+
+rescan-scsi-bus.sh is written by Kurt Garloff (formerly from Suse Labs)
+with patches from Hannes Reinecke (Suse) and Redhat.
+
+scsi_logging_level is written by Andreas Herrmann <aherrman at de dot ibm
+dot com>. It sets the logging level of the SCSI subsystem in the Linux
+2.6 series kernels. See that file for more information.
+
+The other scripts are written by the author. Some do testing while others
+do bulk tasks (e.g. stopping multiple disks).
+
+Details
+=======
+Each script supplies more information, typically by supplying a '-h'
+or '--help' option. The script source often contains explanatory
+information. Following is a usage summary with a one line description:
+ rescan-scsi-bus.sh [OPTIONS]
+ - see the output of 'rescan-scsi-bus.sh --help'
+ scsi_logging_level [OPTIONS]
+ - set Linux SCSI subsystem logging level
+ scsi_mandat [-h] [-L] [-q] <device>
+ - check for mandatory SCSI command support
+ scsi_readcap [-b] [-h] [-v] <device>+
+ - fetch capacity/size information for each <device>
+ scsi_ready [-h] [-v] <device>+
+ - check the media ready status on each <device>
+ scsi_satl [-h] [-L] [-q] [-v] <device>
+ - check <device> for SCSI to ATA Translation Layer (SATL)
+ scsi_start [-h] [-v] [-w] <device>+
+ - start media (i.e. spin up) in each <device>
+ scsi_stop [-h] [-v] [-w] <device>+
+ - stop media (i.e. spin down) in each <device>
+ scsi_temperature [-h] [-v] <device>+
+ - check temperature in each <device>
+
+These scripts assume that the main sg3_utils utilities are installed
+and are on the user's PATH.
+
+This directory, prior to sg3_utils-1.28, contained the sas_disk_blink
+script. Since it depends on the sdparm utility it has been moved to
+the sdparm package in its scripts directory.
+
+59-scsi-sg3_utils.rules is a Linux specific file for udev. These rules use
+'sg_inq --export' to help udev create identifying device nodes, for example
+/dev/disk/by-id/wwn-0x5001501234567890-part1.
+
+Douglas Gilbert
+4th October 2021
diff --git a/scripts/cciss_id b/scripts/cciss_id
new file mode 100755
index 00000000..8ac11d5f
--- /dev/null
+++ b/scripts/cciss_id
@@ -0,0 +1,66 @@
+#!/bin/bash
+#
+# cciss_id
+#
+# Generates device node names according to the cciss naming rules
+#
+# Copyright (C) 2011 SUSE Linux Products GmbH
+# Author:
+# Hannes Reinecke <hare@suse.de>
+#
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation version 2 of the License.
+#
+# This script generates a device node name which is compatible
+# with the 'cciss' device naming rules.
+# It is intended to provide backward-compatible names for the
+# 'hpsa' driver.
+#
+
+cciss_enumerate()
+{
+ local last_pci_dev=${1##0000:}
+ local cur_pci_dev
+ local cciss_num=0
+
+ for cur_pci_dev in $(lspci -n | tac | sed -n 's/\(..:..\..\) .* 103c:\(3220\|3230\|3238\|323a\|323b\) .*/\1/p') ; do
+ if [ "$cur_pci_dev" == "$last_pci_dev" ] ; then
+ echo "$cciss_num"
+ return;
+ fi
+ cciss_num=$(($cciss_num + 1))
+ done
+ echo "$cciss_num"
+}
+
+hpsa_lun_offset()
+{
+ local scsi_host=$1
+
+ scsi_id=$(lsscsi 2>/dev/null | sed -n "s/.\(${scsi_host}:[0-9]*:[0-9]*:[0-9]*\)..*disk .*/\1/p" | head -1)
+ echo ${scsi_id##*:}
+}
+
+DEVPATH=$1
+SCSIPATH=$(cd -P /sys$DEVPATH/device; echo $PWD)
+SCSIID=${SCSIPATH##*/}
+HOSTID=${SCSIID%%:*}
+LUNID=${SCSIID##*:}
+PCIPATH=${SCSIPATH%%/host*}
+PCIDEV=${PCIPATH##*/}
+HOSTPATH=${PCIPATH}/host${HOSTID}/scsi_host/host${HOSTID}
+read controller 2>/dev/null <${HOSTPATH}/ctlr_num || controller=$(cciss_enumerate $PCIDEV)
+
+# hpsa lies about the LUN ...
+disk_offset=$(hpsa_lun_offset $HOSTID)
+if [ "$disk_offset" ] ; then
+ disk=$(( $LUNID - $disk_offset ))
+else
+ disk=$LUNID
+fi
+
+if [ "$controller" ] && [ "$disk" ] ; then
+ echo "ID_CCISS=c${controller}d${disk}"
+fi
diff --git a/scripts/fc_wwpn_id b/scripts/fc_wwpn_id
new file mode 100644
index 00000000..17c74fe8
--- /dev/null
+++ b/scripts/fc_wwpn_id
@@ -0,0 +1,51 @@
+#!/bin/bash
+#
+# fc_wwpn_id
+#
+# Generates device node names links based on FC WWPN
+# Copyright (c) 2016-2021 Hannes Reinecke, SUSE Linux GmbH
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation version 2 of the License.
+#
+
+DEVPATH=$1
+SCSIPATH=$(cd -P "/sys$DEVPATH/device" || exit; echo "$PWD")
+
+d=$SCSIPATH
+[ -d "$d/scsi_disk" ] || exit 0
+target_lun=${d##*:}
+
+while [ -n "$d" ] ; do
+ d=${d%/*}
+ e=${d##*/}
+ case "$e" in
+ rport*)
+ rport=$e
+ rport_dir="/sys/class/fc_remote_ports/$rport"
+ if [ -d "$rport_dir" ] ; then
+ rport_wwpn=$(cat "$rport_dir/port_name")
+ fi
+ ;;
+ host*)
+ host=$e
+ host_dir="/sys/class/fc_host/$host"
+ if [ -d "$host_dir" ] ; then
+ host_wwpn=$(cat "$host_dir/port_name")
+ break;
+ fi
+ esac
+done
+
+if [ -n "$rport_wwpn" ] || [ -n "$host_wwpn" ] ; then
+ echo "FC_TARGET_LUN=$target_lun"
+fi
+
+if [ -n "$rport_wwpn" ] ; then
+ echo "FC_TARGET_WWPN=$rport_wwpn"
+fi
+
+if [ -n "$host_wwpn" ] ; then
+ echo "FC_INITIATOR_WWPN=$host_wwpn"
+fi
diff --git a/scripts/lunmask.service b/scripts/lunmask.service
new file mode 100644
index 00000000..03fdd96a
--- /dev/null
+++ b/scripts/lunmask.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Disable LUN masking and scan SCSI Hosts
+After=systemd-udev-trigger.service
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/usr/lib/systemd/scripts/scsi-enable-target-scan.sh
+
+[Install]
+WantedBy=multi-user.target
diff --git a/scripts/rescan-scsi-bus.sh b/scripts/rescan-scsi-bus.sh
new file mode 100755
index 00000000..1ebc0e91
--- /dev/null
+++ b/scripts/rescan-scsi-bus.sh
@@ -0,0 +1,1436 @@
+#!/bin/bash
+# Script to rescan SCSI bus, using the scsi add-single-device mechanism.
+# (c) 1998--2010 Kurt Garloff <kurt@garloff.de>, GNU GPL v2 or v3
+# (c) 2006--2022 Hannes Reinecke, GNU GPL v2 or later
+# $Id: rescan-scsi-bus.sh,v 1.57 2012/03/31 14:08:48 garloff Exp $
+
+VERSION="20220930"
+SCAN_WILD_CARD=4294967295
+
+TMPLUNINFOFILE="/tmp/rescan-scsi-mpath-info.txt"
+
+setcolor ()
+{
+ red="\e[0;31m"
+ green="\e[0;32m"
+ yellow="\e[0;33m"
+ bold="\e[0;1m"
+ norm="\e[0;0m"
+}
+
+unsetcolor ()
+{
+ red=""; green=""
+ yellow=""; norm=""
+}
+
+echo_debug()
+{
+ if [ "$debug" -eq 1 ] ; then
+ echo "$1"
+ fi
+}
+
+# Output some text and return cursor to previous position
+# (only works for simple strings)
+# Stores length of string in LN and returns it
+print_and_scroll_back ()
+{
+ STRG="$1"
+ LN=${#STRG}
+ BK=""
+ declare -i cntr=0
+ while [ $cntr -lt "$LN" ] ; do BK="$BK\e[D"; let cntr+=1; done
+ echo -en "$STRG$BK"
+ return "$LN"
+}
+
+# Overwrite a text of length $LN with whitespace
+white_out ()
+{
+ BK=""; WH=""
+ declare -i cntr=0
+ while [ $cntr -lt "$LN" ] ; do BK="$BK\e[D"; WH="$WH "; let cntr+=1; done
+ echo -en "$WH$BK"
+}
+
+# Return hosts. sysfs must be mounted
+findhosts_26 ()
+{
+ hosts=
+ for hostdir in /sys/class/scsi_host/host* ; do
+ [ -e "$hostdir" ] || continue
+ hostno=${hostdir#/sys/class/scsi_host/host}
+ if [ -f "$hostdir/isp_name" ] ; then
+ hostname="qla2xxx"
+ elif [ -f "$hostdir/lpfc_drvr_version" ] ; then
+ hostname="lpfc"
+ else
+ hostname=$(cat "$hostdir/proc_name")
+ fi
+ hosts="$hosts $hostno"
+ echo_debug "Host adapter $hostno ($hostname) found."
+ done
+ if [ -z "$hosts" ] ; then
+ echo "No SCSI host adapters found in sysfs"
+ exit 1;
+ fi
+ # ensure numeric ordering. No quotes arount $hosts to skip leading space.
+ hosts=$(echo $hosts | tr ' ' '\n' | sort -n)
+}
+
+# Return hosts. /proc/scsi/HOSTADAPTER/? must exist
+findhosts ()
+{
+ hosts=
+ for driverdir in /proc/scsi/*; do
+ driver=${driverdir#/proc/scsi/}
+ if [ "$driver" = scsi ] || [ "$driver" = sg ] || [ "$driver" = dummy ] || [ "$driver" = device_info ] ; then continue; fi
+ for hostdir in $driverdir/*; do
+ name=${hostdir#/proc/scsi/*/}
+ if [ "$name" = add_map ] || [ "$name" = map ] || [ "$name" = mod_parm ] ; then continue; fi
+ num=$name
+ driverinfo=$driver
+ if [ -r "$hostdir/status" ] ; then
+ num=$(printf '%d\n' "$(sed -n 's/SCSI host number://p' "$hostdir/status")")
+ driverinfo="$driver:$name"
+ fi
+ hosts="$hosts $num"
+ echo "Host adapter $num ($driverinfo) found."
+ done
+ done
+}
+
+printtype ()
+{
+ local type=$1
+
+ case "$type" in
+ 0) echo "Direct-Access" ;;
+ 1) echo "Sequential-Access" ;;
+ 2) echo "Printer" ;;
+ 3) echo "Processor" ;;
+ 4) echo "WORM" ;;
+ 5) echo "CD-ROM" ;;
+ 6) echo "Scanner" ;;
+ 7) echo "Optical-Device" ;;
+ 8) echo "Medium-Changer" ;;
+ 9) echo "Communications" ;;
+ 10) echo "Unknown" ;;
+ 11) echo "Unknown" ;;
+ 12) echo "RAID" ;;
+ 13) echo "Enclosure" ;;
+ 14) echo "Direct-Access-RBC" ;;
+ *) echo "Unknown" ;;
+ esac
+}
+
+print02i()
+{
+ if [ "$1" = "*" ] ; then
+ echo "00"
+ else
+ printf "%02i" "$1"
+ fi
+}
+
+# Get /proc/scsi/scsi info for device $host:$channel:$id:$lun
+# Optional parameter: Number of lines after first (default = 2),
+# result in SCSISTR, return code 1 means empty.
+procscsiscsi ()
+{
+ if [ -z "$1" ] ; then
+ LN=2
+ else
+ LN=$1
+ fi
+ CHANNEL=$(print02i "$channel")
+ ID=$(print02i "$id")
+ LUN=$(print02i "$lun")
+ if [ -d /sys/class/scsi_device ]; then
+ SCSIPATH="/sys/class/scsi_device/${host}:${channel}:${id}:${lun}"
+ if [ -d "$SCSIPATH" ] ; then
+ SCSISTR="Host: scsi${host} Channel: $CHANNEL Id: $ID Lun: $LUN"
+ if [ "$LN" -gt 0 ] ; then
+ IVEND=$(cat "${SCSIPATH}/device/vendor")
+ IPROD=$(cat "${SCSIPATH}/device/model")
+ IPREV=$(cat "${SCSIPATH}/device/rev")
+ SCSIDEV=$(printf ' Vendor: %-08s Model: %-16s Rev: %-4s' "$IVEND" "$IPROD" "$IPREV")
+ SCSISTR="$SCSISTR
+$SCSIDEV"
+ fi
+ if [ "$LN" -gt 1 ] ; then
+ ILVL=$(cat "${SCSIPATH}/device/scsi_level")
+ type=$(cat "${SCSIPATH}/device/type")
+ ITYPE=$(printtype "$type")
+ SCSITMP=$(printf ' Type: %-17s ANSI SCSI revision: %02d' "$ITYPE" "$((ILVL - 1))")
+ SCSISTR="$SCSISTR
+$SCSITMP"
+ fi
+ else
+ return 1
+ fi
+ else
+ grepstr="scsi$host Channel: $CHANNEL Id: $ID Lun: $LUN"
+ SCSISTR=$(grep -A "$LN" -e "$grepstr" /proc/scsi/scsi)
+ fi
+ if [ -z "$SCSISTR" ] ; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+# Find sg device with 2.6 sysfs support
+sgdevice26 ()
+{
+ local gendev
+
+ # if the scsi device has not been added, then there would not
+ # a related sgdev. So it's pointless to scan all sgs to find
+ # a related sg.
+ scsidev=/sys/class/scsi_device/${host}:${channel}:${id}:${lun}
+ if [ ! -e "$scsidev" ]; then
+ SGDEV=""
+ return
+ fi
+
+ gendev=/sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/generic
+ if [ -e "$gendev" ] ; then
+ SGDEV=$(basename "$(readlink "$gendev")")
+ return
+ fi
+ SGDEV=""
+}
+
+# Find sg device with 2.4 report-devs extensions
+sgdevice24 ()
+{
+ if procscsiscsi 3; then
+ SGDEV=$(echo "$SCSISTR" | grep 'Attached drivers:' | sed 's/^ *Attached drivers: \(sg[0-9]*\).*/\1/')
+ fi
+}
+
+# Find sg device that belongs to SCSI device $host $channel $id $lun
+# and return in SGDEV
+sgdevice ()
+{
+ SGDEV=
+ if [ -d /sys/class/scsi_device ] ; then
+ sgdevice26
+ else
+ DRV=$(grep 'Attached drivers:' /proc/scsi/scsi 2>/dev/null)
+ repdevstat=$((1-$?))
+ if [ $repdevstat = 0 ]; then
+ echo "scsi report-devs 1" >/proc/scsi/scsi
+ DRV=$(grep 'Attached drivers:' /proc/scsi/scsi 2>/dev/null)
+ [ $? -eq 1 ] && return
+ fi
+ if ! echo "$DRV" | grep -q 'drivers: sg'; then
+ modprobe sg
+ fi
+ sgdevice24
+ if [ $repdevstat = 0 ]; then
+ echo "scsi report-devs 0" >/proc/scsi/scsi
+ fi
+ fi
+}
+
+# Whether or not the RMB (removable) bit has been set in the INQUIRY response.
+# Uses ${host}, ${channel}, ${id} and ${lun}. Assumes that sg_device() has
+# already been called. How to test this function: copy/paste this function
+# in a shell and run
+# (cd /sys/class/scsi_device && for d in *; do set ${d//:/ }; echo -n "$d $(</sys/class/scsi_device/${d}/device/block/*/removable) <> "; SGDEV=bsg/$d host=$1 channel=$2 id=$3 lun=$4 is_removable; done)
+is_removable ()
+{
+ local b p
+
+ p=/sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device/inquiry
+ # Extract the second byte of the INQUIRY response and check bit 7 (mask 0x80).
+ b=$(hexdump -n1 -e '/1 "%02X"' "$p" 2>/dev/null)
+ if [ -n "$b" ]; then
+ echo $(((0x$b & 0x80) != 0))
+ else
+ sg_inq /dev/$SGDEV 2>/dev/null | sed -n 's/^.*RMB=\([0-9]*\).*$/\1/p'
+ fi
+}
+
+# Test if SCSI device is still responding to commands
+# Return values:
+# 0 device is present
+# 1 device has changed
+# 2 device has been removed
+testonline ()
+{
+ local ctr RC RMB
+
+ : testonline
+ ctr=0
+ RC=0
+ # Set default values
+ IPTYPE=31
+ IPQUAL=3
+ [ ! -x /usr/bin/sg_turs ] && return 0
+ sgdevice
+ [ -z "$SGDEV" ] && return 0
+ sg_turs /dev/$SGDEV >/dev/null 2>&1
+ RC=$?
+
+ # Handle in progress of becoming ready and unit attention
+ while [ $RC = 2 -o $RC = 6 ] && [ $ctr -lt $timeout ] ; do
+ if [ $RC = 2 ] && [ "$RMB" != "1" ] && sg_inq /dev/$SGDEV | grep -q -i "PQual=0" ; then
+ echo -n "."
+ let LN+=1
+ sleep 1
+ else
+ sleep 0.02
+ fi
+ let ctr+=1
+ sg_turs /dev/$SGDEV >/dev/null 2>&1
+ RC=$?
+ # Check for removable device; TEST UNIT READY obviously will
+ # fail for a removable device with no medium
+ RMB=$(is_removable)
+ print_and_scroll_back "$host:$channel:$id:$lun $SGDEV ($RMB) "
+ [ $RC = 2 ] && [ "$RMB" = "1" ] && break
+ done
+ if [ $ctr != 0 ] ; then
+ white_out
+ fi
+ # echo -e "\e[A\e[A\e[A${yellow}Test existence of $SGDEV = $RC ${norm} \n\n\n"
+ [ $RC = 1 ] && return $RC
+ # Reset RC (might be !=0 for passive paths)
+ RC=0
+ # OK, device online, compare INQUIRY string
+ INQ=$(sg_inq "$sg_len_arg" /dev/$SGDEV 2>/dev/null)
+ if [ -z "$INQ" ] ; then
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}INQUIRY failed${norm} \n\n\n"
+ return 2
+ fi
+ IVEND=$(echo "$INQ" | grep 'Vendor identification:' | sed 's/^[^:]*: \(.*\)$/\1/')
+ IPROD=$(echo "$INQ" | grep 'Product identification:' | sed 's/^[^:]*: \(.*\)$/\1/')
+ IPREV=$(echo "$INQ" | grep 'Product revision level:' | sed 's/^[^:]*: \(.*\)$/\1/')
+ STR=$(printf " Vendor: %-08s Model: %-16s Rev: %-4s" "$IVEND" "$IPROD" "$IPREV")
+ IPTYPE=$(echo "$INQ" | sed -n 's/.* Device_type=\([0-9]*\) .*/\1/p')
+ if [ -z "$IPTYPE" ]; then
+ IPTYPE=$(echo "$INQ" | sed -n 's/.* PDT=\([0-9]*\) .*/\1/p')
+ fi
+ IPQUAL=$(echo "$INQ" | sed -n 's/ *PQual=\([0-9]*\) Device.*/\1/p')
+ if [ -z "$IPQUAL" ] ; then
+ IPQUAL=$(echo "$INQ" | sed -n 's/ *PQual=\([0-9]*\) PDT.*/\1/p')
+ fi
+ if [ "$IPQUAL" != 0 ] ; then
+ [ -z "$IPQUAL" ] && IPQUAL=3
+ [ -z "$IPTYPE" ] && IPTYPE=31
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}LU not available (PQual $IPQUAL)${norm} \n\n\n"
+ return 2
+ fi
+
+ TYPE=$(printtype $IPTYPE)
+ if ! procscsiscsi ; then
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV removed. ${norm}\n\n\n"
+ return 2
+ fi
+ TMPSTR=$(echo "$SCSISTR" | grep 'Vendor:')
+ if [ "$ignore_rev" -eq 0 ] ; then
+ if [ "$TMPSTR" != "$STR" ]; then
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${SCSISTR#* } \nto: $STR ${norm} \n\n\n"
+ return 1
+ fi
+ else
+ # Ignore disk revision change
+ local old_str_no_rev=
+ local new_str_no_rev=
+
+ old_str_no_rev=${TMPSTR%Rev:*}
+ new_str_no_rev=${STR%Rev:*}
+ if [ "$old_str_no_rev" != "$new_str_no_rev" ]; then
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${SCSISTR#* } \nto: $STR ${norm} \n\n\n"
+ return 1
+ fi
+ fi
+ TMPSTR=$(echo "$SCSISTR" | sed -n 's/.*Type: *\(.*\) *ANSI.*/\1/p' | sed 's/ *$//g')
+ if [ "$TMPSTR" != "$TYPE" ] ; then
+ echo -e "\e[A\e[A\e[A\e[A${red}$SGDEV changed: ${bold}\nfrom:${TMPSTR} \nto: $TYPE ${norm} \n\n\n"
+ return 1
+ fi
+ return $RC
+}
+
+# Test if SCSI device $host $channel $id $lun exists
+# Outputs description from /proc/scsi/scsi (unless arg passed)
+# Returns SCSISTR (empty if no dev)
+testexist ()
+{
+ : testexist
+ SCSISTR=
+ if procscsiscsi && [ -z "$1" ] ; then
+ echo "$SCSISTR" | head -n1
+ echo "$SCSISTR" | tail -n2 | pr -o4 -l1
+ fi
+}
+
+# Returns the list of existing channels per host
+chanlist ()
+{
+ local hcil
+ local cil
+ local chan
+ local tmpchan
+
+ for dev in /sys/class/scsi_device/${host}:* ; do
+ [ -d "$dev" ] || continue;
+ hcil=${dev##*/}
+ cil=${hcil#*:}
+ chan=${cil%%:*}
+ for tmpchan in $channelsearch ; do
+ if [ "$chan" -eq "$tmpchan" ] ; then
+ chan=
+ fi
+ done
+ if [ -n "$chan" ] ; then
+ channelsearch="$channelsearch $chan"
+ fi
+ done
+ if [ -z "$channelsearch" ] ; then
+ channelsearch="0"
+ fi
+}
+
+# Returns the list of existing targets per host
+idlist ()
+{
+ local tmpid
+ local newid
+ local oldid
+
+ oldlist=$(find /sys/class/scsi_device -name "${host}:${channel}:*" -printf "%f\n")
+ # Rescan LUN 0 to check if we found new targets
+ echo "${channel} - -" > "/sys/class/scsi_host/host${host}/scan"
+ newlist=$(find /sys/class/scsi_device -name "${host}:${channel}:*" -printf "%f\n")
+ for newid in $newlist ; do
+ oldid=$newid
+ for tmpid in $oldlist ; do
+ if [ "$newid" = "$tmpid" ] ; then
+ oldid=
+ break
+ fi
+ done
+ if [ -n "$oldid" ] ; then
+ if [ -d /sys/class/scsi_device/$oldid ] ; then
+ hcil=${oldid}
+ printf "\r${green}NEW: %s ${norm}"
+ testexist
+ if [ "$SCSISTR" ] ; then
+ incrfound "$hcil"
+ fi
+ fi
+ fi
+ done
+ idsearch=$(find /sys/bus/scsi/devices -name "target${host}:${channel}:*" -printf "%f\n" | cut -f 3 -d :)
+}
+
+# Returns the list of existing LUNs from device $host $channel $id $lun
+# and returns list to stdout
+getluns()
+{
+ sgdevice
+ [ -z "$SGDEV" ] && return 1
+ if [ ! -x /usr/bin/sg_luns ] ; then
+ echo 0
+ return 1
+ fi
+ LLUN=$(sg_luns /dev/$SGDEV 2>/dev/null | sed -n 's/ \(.*\)/\1/p')
+ # Added -z $LLUN condition because $? gets the RC from sed, not sg_luns
+ if [ $? -ne 0 ] || [ -z "$LLUN" ] ; then
+ echo 0
+ return 1
+ fi
+ for lun in $LLUN ; do
+ # Swap LUN number
+ l0=0x$lun
+ l1=$(( (l0 >> 48) & 0xffff ))
+ l2=$(( (l0 >> 32) & 0xffff ))
+ l3=$(( (l0 >> 16) & 0xffff ))
+ l4=$(( l0 & 0xffff ))
+ l0=$(( ( ( (l4 * 0xffff) + l3 ) * 0xffff + l2 ) * 0xffff + l1 ))
+ printf "%u\n" $l0
+ done
+ return 0
+}
+
+# Wait for udev to settle (create device nodes etc.)
+udevadm_settle()
+{
+ local tmo=60
+ if [ -x /sbin/udevadm ] ; then
+ print_and_scroll_back " Calling udevadm settle (can take a while) "
+ # Loop for up to 60 seconds if sd devices still are settling..
+ # This allows us to continue if udev events are stuck on multipaths in recovery mode
+ while [ $tmo -gt 0 ] ; do
+ if ! /sbin/udevadm settle --timeout=1 | egrep -q sd[a-z]+ ; then
+ break;
+ fi
+ let tmo=$tmo-1
+ done
+ white_out
+ elif [ -x /sbin/udevsettle ] ; then
+ print_and_scroll_back " Calling udevsettle (can take a while) "
+ /sbin/udevsettle
+ white_out
+ else
+ sleep 0.02
+ fi
+}
+
+# Perform scan on a single lun $host $channel $id $lun
+dolunscan()
+{
+ local remappedlun0=
+ local devpath
+ SCSISTR=
+ devnr="$host $channel $id $lun"
+ echo -e " Scanning for device $devnr ... "
+ printf "${yellow}OLD: %s ${norm}"
+ testexist
+ # Device exists: Test whether it's still online
+ # (testonline returns 2 if it's gone and 1 if it has changed)
+ devpath="/sys/class/scsi_device/${host}:${channel}:${id}:${lun}/device"
+ if [ "$SCSISTR" ] ; then
+ testonline
+ RC=$?
+ # Well known lun transition case. Only for Direct-Access devs (type 0)
+ # If block directory exists && and PQUAL != 0, we unmapped lun0 and just have a well-known lun
+ # If block directory doesn't exist && PQUAL == 0, we mapped a real lun0
+ if [ "$lun" -eq 0 ] && [ $IPTYPE -eq 0 ] ; then
+ if [ $RC = 2 ] ; then
+ if [ -e "$devpath" ] ; then
+ if [ -d "$devpath/block" ] ; then
+ remappedlun0=2 # Transition from real lun 0 to well-known
+ else
+ RC=0 # Set this so the system leaves the existing well known lun alone. This is a lun 0 with no block directory
+ fi
+ fi
+ elif [ $RC = 0 ] && [ $IPTYPE -eq 0 ] ; then
+ if [ -e "$devpath" ] ; then
+ if [ ! -d "$devpath/block" ] ; then
+ remappedlun0=1 # Transition from well-known to real lun 0
+ fi
+ fi
+ fi
+ fi
+ fi
+
+ # Special case: lun 0 just got added (for reportlunscan),
+ # so make sure we correctly treat it as new
+ if [ "$lun" = "0" ] && [ "$1" = "1" ] && [ -z "$remappedlun0" ] ; then
+ SCSISTR=""
+ printf "\r\e[A\e[A\e[A"
+ fi
+
+ : f "$remove" s $SCSISTR
+ if [ "$remove" ] && [ "$SCSISTR" -o "$remappedlun0" = "1" ] ; then
+ if [ $RC != 0 ] || [ ! -z "$forceremove" ] || [ -n "$remappedlun0" ] ; then
+ if [ "$remappedlun0" != "1" ] ; then
+ echo -en "\r\e[A\e[A\e[A${red}REM: "
+ echo "$SCSISTR" | head -n1
+ echo -e "${norm}\e[B\e[B"
+ fi
+ if [ -e "$devpath" ] ; then
+ # have to preemptively do this so we can figure out the mpath device
+ # Don't do this if we're deleting a well known lun to replace it
+ if [ "$remappedlun0" != "1" ] ; then
+ incrrmvd "$host:$channel:$id:$lun"
+ fi
+ echo 1 > "$devpath/delete"
+ sleep 0.02
+ else
+ echo "scsi remove-single-device $devnr" > /proc/scsi/scsi
+ if [ $RC -eq 1 ] || [ "$lun" -eq 0 ] ; then
+ # Try readding, should fail if device is gone
+ echo "scsi add-single-device $devnr" > /proc/scsi/scsi
+ fi
+ fi
+ fi
+ if [ $RC = 0 ] || [ "$forcerescan" ] ; then
+ if [ -e "$devpath" ] ; then
+ echo 1 > "$devpath/rescan"
+ fi
+ fi
+ printf "\r\e[A\e[A\e[A${yellow}OLD: %s ${norm}"
+ testexist
+ if [ -z "$SCSISTR" ] && [ $RC != 1 ] && [ "$remappedlun0" != "1" ] ; then
+ printf "\r${red}DEL: %s\r\n\n ${norm}"
+ # In the event we're replacing with a well known node, we need to let it continue, to create the replacement node
+ [ "$remappedlun0" != "2" ] && return 2
+ fi
+ fi
+ if [ -z "$SCSISTR" ] || [ -n "$remappedlun0" ] ; then
+ if [ "$remappedlun0" != "2" ] ; then
+ # Device does not exist, try to add
+ printf "\r${green}NEW: %s ${norm}"
+ fi
+ if [ -e "/sys/class/scsi_host/host${host}/scan" ] ; then
+ echo "$channel $id $lun" > "/sys/class/scsi_host/host${host}/scan" 2> /dev/null
+ else
+ echo "scsi add-single-device $devnr" > /proc/scsi/scsi
+ fi
+ testexist
+ if [ -z "$SCSISTR" ] ; then
+ # Device not present
+ printf "\r\e[A";
+ # Optimization: if lun==0, stop here (only if in non-remove mode)
+ if [ "$lun" = 0 ] && [ -z "$remove" ] && [ "$optscan" = 1 ] ; then
+ return 1;
+ fi
+ else
+ if [ "$remappedlun0" != "2" ] ; then
+ incrfound "$host:$channel:$id:$lun"
+ fi
+ fi
+ fi
+ return 0;
+}
+
+# Perform report lun scan on $host $channel $id using REPORT_LUNS
+doreportlun()
+{
+ lun=0
+ SCSISTR=
+ devnr="$host $channel $id $lun"
+ echo -en " Scanning for device $devnr ...\r"
+ lun0added=
+ #printf "${yellow}OLD: %s ${norm}"
+ # Phase one: If LUN0 does not exist, try to add
+ testexist -q
+ if [ -z "$SCSISTR" ] ; then
+ # Device does not exist, try to add
+ #printf "\r${green}NEW: %s ${norm}"
+ if [ -e "/sys/class/scsi_host/host${host}/scan" ] ; then
+ echo "$channel $id $lun" > "/sys/class/scsi_host/host${host}/scan" 2> /dev/null
+ udevadm_settle
+ else
+ echo "scsi add-single-device $devnr" > /proc/scsi/scsi
+ fi
+ testexist -q
+ if [ -n "$SCSISTR" ] ; then
+ lun0added=1
+ #testonline
+ else
+ # Device not present
+ # return
+ # Find alternative LUN to send getluns to
+ for dev in /sys/class/scsi_device/${host}:${channel}:${id}:*; do
+ [ -d "$dev" ] || continue
+ lun=${dev##*:}
+ break
+ done
+ fi
+ fi
+ targetluns=$(getluns)
+ REPLUNSTAT=$?
+ lunremove=
+ #echo "getluns reports " $targetluns
+ olddev=$(find /sys/class/scsi_device/ -name "$host:$channel:$id:*" 2>/dev/null | sort -t: -k4 -n)
+ oldtargets="$targetluns"
+ # OK -- if we don't have a LUN to send a REPORT_LUNS to, we could
+ # fall back to wildcard scanning. Same thing if the device does not
+ # support REPORT_LUNS
+ # TODO: We might be better off to ALWAYS use wildcard scanning if
+ # it works
+ if [ "$REPLUNSTAT" = "1" ] ; then
+ if [ -e "/sys/class/scsi_host/host${host}/scan" ] ; then
+ echo "$channel $id -" > "/sys/class/scsi_host/host${host}/scan" 2> /dev/null
+ udevadm_settle
+ else
+ echo "scsi add-single-device $host $channel $id $SCAN_WILD_CARD" > /proc/scsi/scsi
+ fi
+ targetluns=$(find /sys/class/scsi_device/ -name "$host:$channel:$id:*" -printf "%f\n" | cut -d : -f 4)
+ let found+=$(echo "$targetluns" | wc -l)
+ let found-=$(echo "$olddev" | wc -l)
+ fi
+ [ -z "$targetluns" ] && targetluns="$oldtargets"
+ # Check existing luns
+ for dev in $olddev; do
+ [ -d "$dev" ] || continue
+ lun=${dev##*:}
+ newsearch=
+ inlist=
+ # OK, is existing $lun (still) in reported list
+ for tmplun in $targetluns; do
+ if [ "$tmplun" = "$lun" ] ; then
+ inlist=1
+ dolunscan $lun0added
+ [ $? -eq 1 ] && break
+ else
+ newsearch="$newsearch $tmplun"
+ fi
+ done
+ # OK, we have now done a lunscan on $lun and
+ # $newsearch is the old $targetluns without $lun
+ if [ -z "$inlist" ]; then
+ # Stale lun
+ lunremove="$lunremove $lun"
+ fi
+ # $lun removed from $lunsearch
+ targetluns=${newsearch# }
+ done
+ # Add new ones and check stale ones
+ for lun in $targetluns $lunremove; do
+ dolunscan $lun0added
+ [ $? -eq 1 ] && break
+ done
+}
+
+# Perform search (scan $host)
+dosearch ()
+{
+ if [ -z "$channelsearch" ] ; then
+ chanlist
+ fi
+ for channel in $channelsearch; do
+ if [ -z "$idsearch" ] ; then
+ if [ -z "$lunsearch" ] ; then
+ idlist
+ else
+ idsearch=$(find /sys/bus/scsi/devices -name "target${host}:${channel}:*" -printf "%f\n" | cut -f 3 -d :)
+ fi
+ fi
+ for id in $idsearch; do
+ if [ -z "$lunsearch" ] ; then
+ doreportlun
+ else
+ for lun in $lunsearch; do
+ dolunscan
+ [ $? -eq 1 ] && break
+ done
+ fi
+ done
+ done
+}
+
+expandlist ()
+{
+ list=$1
+ result=""
+ first=${list%%,*}
+ rest=${list#*,}
+ while [ ! -z "$first" ] ; do
+ beg=${first%%-*};
+ if [ "$beg" = "$first" ] ; then
+ result="$result $beg";
+ else
+ end=${first#*-}
+ result="$result $(seq -s ' ' $beg $end)"
+ fi
+ [ "$rest" = "$first" ] && rest=""
+ first=${rest%%,*}
+ rest=${rest#*,}
+ done
+ echo "$result"
+}
+
+searchexisting()
+{
+ local tmpch;
+ local tmpid
+ local match=0
+ local targets=
+
+ targets=$(find /sys/bus/scsi/devices -name "target${host}:*" -printf "%f\n" | cut -d : -f 2-3)
+ # Nothing came back on this host, so we should skip it
+ [ -z "$targets" ] && return
+
+ local target=;
+ for target in $targets ; do
+ channel=${target%:*}
+ id=${target#*:}
+ if [ -n "$channelsearch" ] ; then
+ for tmpch in $channelsearch ; do
+ [ $tmpch -eq "$channel" ] && match=1
+ done
+ else
+ match=1
+ fi
+
+ [ $match -eq 0 ] && continue
+ match=0
+
+ if [ "$filter_ids" -eq 1 ] ; then
+ for tmpid in $idsearch ; do
+ if [ "$tmpid" = "$id" ] ; then
+ match=1
+ fi
+ done
+ else
+ match=1
+ fi
+
+ [ $match -eq 0 ] && continue
+
+ if [ -z "$lunsearch" ] ; then
+ doreportlun
+ else
+ for lun in $lunsearch ; do
+ dolunscan
+ [ $? -eq 1 ] && break
+ done
+ fi
+ done
+}
+
+getallmultipathinfo()
+{
+ local mp=
+ local uuid=
+ local dmtmp=
+ local maj_min=
+ local tmpfile=
+
+ truncate -s 0 $TMPLUNINFOFILE
+ for mp in $($DMSETUP ls --target=multipath | cut -f 1) ; do
+ [ "$mp" = "No" ] && break;
+ maj_min=$($DMSETUP status "$mp" | cut -d " " -f14)
+ if [ ! -L /dev/mapper/${mp} ]; then
+ echo "softlink /dev/mapper/${mp} not available."
+ continue
+ fi
+ local ret=$(readlink /dev/mapper/$mp 2>/dev/null)
+ if [[ $? -ne 0 || -z "$ret" ]]; then
+ echo "readlink /dev/mapper/$mp failed. check multipath status."
+ continue
+ fi
+ dmtmp=$(basename $ret)
+ uuid=$(cut -f2 -d- "/sys/block/$dmtmp/dm/uuid")
+ echo "$mp $maj_min $dmtmp $uuid" >> $TMPLUNINFOFILE
+ done
+}
+
+# Go through all of the existing devices and figure out any that have been remapped
+findremapped()
+{
+ local hctl=;
+ local devs=
+ local sddev=
+ local id_serial=
+ local id_serial_old=
+ local remapped=
+ mpaths=""
+ local tmpfile=
+
+ tmpfile=$(mktemp /tmp/rescan-scsi-bus.XXXXXXXX 2> /dev/null)
+ if [ -z "$tmpfile" ] ; then
+ tmpfile="/tmp/rescan-scsi-bus.$$"
+ rm -f $tmpfile
+ fi
+
+ # Get all of the ID_SERIAL attributes, after finding their sd node
+ devs=$(ls /sys/class/scsi_device/)
+ for hctl in $devs ; do
+ if [ -d "/sys/class/scsi_device/$hctl/device/block" ] ; then
+ sddev=$(ls "/sys/class/scsi_device/$hctl/device/block")
+ id_serial_old=$(udevadm info -q all -n "$sddev" | grep "ID_SERIAL=" | cut -d"=" -f2)
+ [ -z "$id_serial_old" ] && id_serial_old="none"
+ echo "$hctl $sddev $id_serial_old" >> $tmpfile
+ fi
+ done
+
+ # Trigger udev to update the info
+ echo -n "Triggering udev to update device information... "
+ /sbin/udevadm trigger
+ udevadm_settle 2>&1 /dev/null
+ echo "Done"
+
+ getallmultipathinfo
+
+ # See what changed and reload the respective multipath device if applicable
+ while read -r hctl sddev id_serial_old ; do
+ remapped=0
+ id_serial=$(udevadm info -q all -n "$sddev" | grep "ID_SERIAL=" | cut -d"=" -f2)
+ [ -z "$id_serial" ] && id_serial="none"
+ if [ "$id_serial_old" != "$id_serial" ] ; then
+ remapped=1
+ fi
+ # If udev events updated the disks already, but the multipath device isn't update
+ # check for old devices to make sure we found remapped luns
+ if [ -n "$mp_enable" ] && [ $remapped -eq 0 ]; then
+ findmultipath "$sddev" $id_serial
+ if [ $? -eq 1 ] ; then
+ remapped=1
+ fi
+ fi
+
+ # if uuid is 1, it's unmapped, so we don't want to treat it as a remap
+ # if remapped flag is 0, just skip the rest of the logic
+ if [ "$id_serial" = "1" ] || [ $remapped -eq 0 ] ; then
+ continue
+ fi
+ printf "${yellow}REMAPPED: %s ${norm}"
+ host=$(echo "$hctl" | cut -d":" -f1)
+ channel=$(echo "$hctl" | cut -d":" -f2)
+ id=$(echo "$hctl" | cut -d":" -f3)
+ lun=$(echo "$hctl" | cut -d":" -f4)
+ procscsiscsi
+ echo "$SCSISTR"
+ incrchgd "$hctl"
+ done < $tmpfile
+ rm -f $tmpfile
+
+ if [ -n "$mp_enable" ] && [ -n "$mpaths" ] ; then
+ echo "Updating multipath device mappings"
+ flushmpaths
+ $MULTIPATH | grep "create:" 2> /dev/null
+ fi
+}
+
+incrfound()
+{
+ local hctl="$1"
+ if [ -n "$hctl" ] ; then
+ let found+=1
+ FOUNDDEVS="$FOUNDDEVS\t[$hctl]\n"
+ else
+ return
+ fi
+}
+
+incrchgd()
+{
+ local hctl="$1"
+ if [ -n "$hctl" ] ; then
+ if ! echo "$CHGDEVS" | grep -q "\[$hctl\]"; then
+ let updated+=1
+ CHGDEVS="$CHGDEVS\t[$hctl]\n"
+ fi
+ else
+ return
+ fi
+
+ if [ -n "$mp_enable" ] ; then
+ local sdev
+
+ sdev=$(findsddev "$hctl")
+ if [ -n "$sdev" ] ; then
+ findmultipath "$sdev"
+ fi
+ fi
+}
+
+incrrmvd()
+{
+ local hctl="$1"
+ if [ -n "$hctl" ] ; then
+ let rmvd+=1;
+ RMVDDEVS="$RMVDDEVS\t[$hctl]\n"
+ else
+ return
+ fi
+
+ if [ -n "$mp_enable" ] ; then
+ local sdev
+
+ sdev=$(findsddev "$hctl")
+ if [ -n "$sdev" ] ; then
+ findmultipath "$sdev"
+ fi
+ fi
+}
+
+findsddev()
+{
+ local hctl="$1"
+ local sddev=
+ local blkpath
+
+ blkpath="/sys/class/scsi_device/$hctl/device/block"
+ if [ -e "$blkpath" ] ; then
+ sddev=$(ls "$blkpath")
+ echo "$sddev"
+ fi
+}
+
+addmpathtolist()
+{
+ local mp="$1"
+ local mp2=
+
+ for mp2 in $mpaths ; do
+ # The multipath device is already in the list
+ if [ "$mp2" = "$mp" ] ; then
+ return
+ fi
+ done
+ mpaths="$mpaths $mp"
+}
+
+findmultipath()
+{
+ local dev="$1"
+ local find_mismatch="$2"
+ local mp=
+ local found_dup=0
+ local maj_min=
+
+ # Need a sdev, and executable multipath and dmsetup command here
+ if [ -z "$dev" ] || [ ! -x "$DMSETUP" ] || [ ! -x "$MULTIPATH" ] ; then
+ return 1
+ fi
+
+ maj_min=$(cat "/sys/block/$dev/dev")
+ mp=$(cat $TMPLUNINFOFILE | grep -w "$maj_min" | cut -d " " -f1)
+ if [ -n "$mp" ]; then
+ if [ -n "$find_mismatch" ] ; then
+ uuid=$(cat $TMPLUNINFOFILE | grep -w "$maj_min" | cut -d " " -f4)
+ if [ "$find_mismatch" != "$uuid" ] ; then
+ addmpathtolist "$mp"
+ found_dup=1
+ fi
+ else
+ # Normal mode: Find the first multipath with the sdev
+ # and add it to the list
+ addmpathtolist "$mp"
+ return
+ fi
+ fi
+
+ # Return 1 to signal that a duplicate was found to the calling function
+ if [ $found_dup -eq 1 ] ; then
+ return 1
+ else
+ return 0
+ fi
+}
+
+reloadmpaths()
+{
+ local mpath
+ if [ ! -x "$MULTIPATH" ] ; then
+ echo "no -x multipath"
+ return
+ fi
+
+ # Pass 1 as the argument to reload all mpaths
+ if [ "$1" = "1" ] ; then
+ echo "Reloading all multipath devices"
+ $MULTIPATH -r > /dev/null 2>&1
+ return
+ fi
+
+ # Reload the multipath devices
+ for mpath in $mpaths ; do
+ echo -n "Reloading multipath device $mpath... "
+ if $MULTIPATH -r "$mpath" > /dev/null 2>&1 ; then
+ echo "Done"
+ else
+ echo "Fail"
+ fi
+ done
+}
+
+resizempaths()
+{
+ local mpath
+
+ for mpath in $mpaths ; do
+ echo -n "Resizing multipath map $mpath ..."
+ multipathd -k"resize map $mpath"
+ let updated+=1
+ done
+}
+
+flushmpaths()
+{
+ local mpath
+ local remove=""
+ local i
+ local flush_retries=5
+
+ if [ -n "$1" ] ; then
+ for mpath in $($DMSETUP ls --target=multipath | cut -f 1) ; do
+ [ "$mpath" = "No" ] && break
+ num=$($DMSETUP status "$mpath" | awk 'BEGIN{RS=" ";active=0}/[0-9]+:[0-9]+/{dev=1}/A/{if (dev == 1) active++; dev=0} END{ print active }')
+ if [ "$num" -eq 0 ] ; then
+ remove="$remove $mpath"
+ fi
+ done
+ else
+ remove="$mpaths"
+ fi
+
+ for mpath in $remove ; do
+ i=0
+ echo -n "Flushing multipath device $mpath... "
+ while [ $i -lt $flush_retries ] ; do
+ $DMSETUP message "$mpath" 0 fail_if_no_path > /dev/null 2>&1
+ if $MULTIPATH -f "$mpath" > /dev/null 2>&1 ; then
+ echo "Done ($i retries)"
+ break
+ elif [ $i -eq $flush_retries ] ; then
+ echo "Fail"
+ fi
+ sleep 0.02
+ let i=$i+1
+ done
+ done
+}
+
+
+# Find resized luns
+findresized()
+{
+ local devs=
+ local size=
+ local new_size=
+ local sysfs_path=
+ local sddev=
+ local i=
+ local m=
+ local mpathsize=
+ declare -a mpathsizes
+
+ if [ -z "$lunsearch" ] ; then
+ devs=$(ls /sys/class/scsi_device/)
+ else
+ for lun in $lunsearch ; do
+ devs="$devs $(cd /sys/class/scsi_device/ && ls -d *:${lun})"
+ done
+ fi
+
+ for hctl in $devs ; do
+ sysfs_path="/sys/class/scsi_device/$hctl/device"
+ if [ -d "$sysfs_path/block" ] ; then
+ sddev=$(ls "$sysfs_path/block")
+ size=$(cat "$sysfs_path/block/$sddev/size")
+
+ echo 1 > "$sysfs_path/rescan"
+ new_size=$(cat "$sysfs_path/block/$sddev/size")
+
+ if [ "$size" != "$new_size" ] && [ "$size" != "0" ] && [ "$new_size" != "0" ] ; then
+ printf "${yellow}RESIZED: %s ${norm}"
+ host=$(echo "$hctl" | cut -d":" -f1)
+ channel=$(echo "$hctl" | cut -d":" -f2)
+ id=$(echo "$hctl" | cut -d":" -f3)
+ lun=$(echo "$hctl" | cut -d":" -f4)
+
+ procscsiscsi
+ echo "$SCSISTR"
+ incrchgd "$hctl"
+ fi
+ fi
+ done
+
+ if [ -n "$mp_enable" ] && [ -n "$mpaths" ] ; then
+ i=0
+ for m in $mpaths ; do
+ mpathsizes[$i]="$($MULTIPATH -l "$m" | egrep -o [0-9]+.[0-9]+[KMGT])"
+ let i=$i+1
+ done
+ resizempaths
+ i=0
+ for m in $mpaths ; do
+ mpathsize="$($MULTIPATH -l "$m" | egrep -o [0-9\.]+[KMGT])"
+ echo "$m ${mpathsizes[$i]} => $mpathsize"
+ let i=$i+1
+ done
+ fi
+}
+
+FOUNDDEVS=""
+CHGDEVS=""
+RMVDDEVS=""
+
+# main
+if [ "@$1" = @--help ] || [ "@$1" = @-h ] || [ "@$1" = "@-?" ] ; then
+ echo "Usage: rescan-scsi-bus.sh [options] [host [host ...]]"
+ echo "Options:"
+ echo " -a scan all targets, not just currently existing [default: disabled]"
+ echo " -c enables scanning of channels 0 1 [default: 0 / all detected ones]"
+ echo " -d enable debug [default: 0]"
+ echo " -f flush failed multipath devices [default: disabled]"
+ echo " -h help: print this usage message then exit"
+ echo " -i issue a FibreChannel LIP reset [default: disabled]"
+ echo " -I SECS issue a FibreChannel LIP reset and wait for SECS seconds [default: disabled]"
+ echo " -l activates scanning for LUNs 0--7 [default: 0]"
+ echo " -L NUM activates scanning for LUNs 0--NUM [default: 0]"
+ echo " -m update multipath devices [default: disabled]"
+ echo " -r enables removing of devices [default: disabled]"
+ echo " -s look for resized disks and reload associated multipath devices, if applicable"
+ echo " -t SECS timeout for testing if device is online. Test is skipped if 0 [default: 30]"
+ echo " -u look for existing disks that have been remapped"
+ echo " -V print version date then exit"
+ echo " -w scan for target device IDs 0--15 [default: 0--7]"
+ echo "--alltargets: same as -a"
+ echo "--attachpq3: Tell kernel to attach sg to LUN 0 that reports PQ=3"
+ echo "--channels=LIST: Scan only channel(s) in LIST"
+ echo "--color: use coloured prefixes OLD/NEW/DEL"
+ echo "--flush: same as -f"
+ echo "--forceremove: Remove stale devices (DANGEROUS)"
+ echo "--forcerescan: Remove and readd existing devices (DANGEROUS)"
+ echo "--help: print this usage message then exit"
+ echo "--hosts=LIST: Scan only host(s) in LIST"
+ echo "--ids=LIST: Scan only target ID(s) in LIST"
+ echo "--ignore-rev: Ignore the revision change"
+ echo "--issue-lip: same as -i"
+ echo "--issue-lip-wait=SECS: same as -I"
+ echo "--largelun: Tell kernel to support LUNs > 7 even on SCSI2 devs"
+ echo "--luns=LIST: Scan only lun(s) in LIST"
+ echo "--multipath: same as -m"
+ echo "--no-lip-scan: don't scan FC Host with issue-lip"
+ echo "--nooptscan: don't stop looking for LUNs if 0 is not found"
+ echo "--remove: same as -r"
+ echo "--reportlun2: Tell kernel to try REPORT_LUN even on SCSI2 devices"
+ echo "--resize: same as -s"
+ echo "--sparselun: Tell kernel to support sparse LUN numbering"
+ echo "--sync/nosync: Issue a sync / no sync [default: sync if remove]"
+ echo "--timeout=SECS: same as -t"
+ echo "--update: same as -u"
+ echo "--version: same as -V"
+ echo "--wide: same as -w"
+ echo ""
+ echo "Host numbers may thus be specified either directly on cmd line (deprecated)"
+ echo "or with the --hosts=LIST parameter (recommended)."
+ echo "LIST: A[-B][,C[-D]]... is a comma separated list of single values and ranges"
+ echo "(No spaces allowed.)"
+ exit 0
+fi
+
+if [ "@$1" = @--version ] || [ "@$1" = @-V ] ; then
+ echo ${VERSION}
+ exit 0
+fi
+
+if [ ! -d /sys/class/scsi_host/ ] && [ ! -d /proc/scsi/ ] ; then
+ echo "Error: SCSI subsystem not active"
+ exit 1
+fi
+
+# Make sure sg is there
+modprobe sg >/dev/null 2>&1
+
+if [ -x /usr/bin/sg_inq ] ; then
+ sg_version=$(sg_inq -V 2>&1 | cut -d " " -f 3)
+ if [ -n "$sg_version" ] ; then
+ sg_ver_maj=${sg_version:0:1}
+ sg_version=${sg_version##?.}
+ let sg_version+=$((100 * sg_ver_maj))
+ fi
+ sg_version=${sg_version##0.}
+ #echo "\"$sg_version\""
+ if [ -z "$sg_version" ] || [ "$sg_version" -lt 70 ] ; then
+ sg_len_arg="-36"
+ else
+ sg_len_arg="--len=36"
+ fi
+else
+ echo "WARN: /usr/bin/sg_inq not present -- please install sg3_utils"
+ echo " or rescan-scsi-bus.sh might not fully work."
+fi
+
+# defaults
+unsetcolor
+debug=0
+lunsearch=
+opt_idsearch=$(seq -s ' ' 0 7)
+filter_ids=0
+opt_channelsearch=
+remove=
+updated=0
+update=0
+resize=0
+forceremove=
+optscan=1
+sync=1
+existing_targets=1
+mp_enable=
+lipreset=-1
+timeout=30
+declare -i scan_flags=0
+ignore_rev=0
+no_lip_scan=0
+
+# Scan options
+opt="$1"
+while [ ! -z "$opt" ] && [ -z "${opt##-*}" ] ; do
+ opt=${opt#-}
+ case "$opt" in
+ a) existing_targets=;; #Scan ALL targets when specified
+ c) opt_channelsearch="0 1" ;;
+ d) debug=1 ;;
+ f) flush=1 ;;
+ i) lipreset=0 ;;
+ I) shift; lipreset=$1 ;;
+ l) lunsearch=$(seq -s ' ' 0 7) ;;
+ L) lunsearch=$(seq -s ' ' 0 "$2"); shift ;;
+ m) mp_enable=1 ;;
+ r) remove=1 ;;
+ s) resize=1; mp_enable=1 ;;
+ t) timeout=$2; shift ;;
+ u) update=1 ;;
+ w) opt_idsearch=$(seq -s ' ' 0 15) ;;
+ -alltargets) existing_targets=;;
+ -attachpq3) scan_flags=$((scan_flags|0x1000000)) ;;
+ -channels=*) arg=${opt#-channels=};opt_channelsearch=$(expandlist "$arg") ;;
+ -color) setcolor ;;
+ -flush) flush=1 ;;
+ -forceremove) remove=1; forceremove=1 ;;
+ -forcerescan) remove=1; forcerescan=1 ;;
+ -hosts=*) arg=${opt#-hosts=}; hosts=$(expandlist "$arg") ;;
+ -ids=*) arg=${opt#-ids=}; opt_idsearch=$(expandlist "$arg") ; filter_ids=1;;
+ -ignore-rev) ignore_rev=1;;
+ -issue-lip) lipreset=0 ;;
+ -issue-lip-wait=*) lipreset=${opt#-issue-lip-wait=};;
+ -largelun) scan_flags=$((scan_flags|0x200)) ;;
+ -luns=*) arg=${opt#-luns=}; lunsearch=$(expandlist "$arg") ;;
+ -multipath) mp_enable=1 ;;
+ -no-lip-scan) no_lip_scan=1 ;;
+ -nooptscan) optscan=0 ;;
+ -nosync) sync=0 ;;
+ -remove) remove=1 ;;
+ -reportlun2) scan_flags=$((scan_flags|0x20000)) ;;
+ -resize) resize=1;;
+ -timeout=*) timeout=${opt#-timeout=};;
+ -sparselun) scan_flags=$((scan_flags|0x40)) ;;
+ -sync) sync=2 ;;
+ -update) update=1;;
+ -wide) opt_idsearch=$(seq -s ' ' 0 15) ;;
+ *) echo "Unknown option -$opt !" ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ -z "$hosts" ] ; then
+ if [ -d /sys/class/scsi_host ] ; then
+ findhosts_26
+ else
+ findhosts
+ fi
+fi
+
+if [ -d /sys/class/scsi_host ] && [ ! -w /sys/class/scsi_host ]; then
+ echo "You need to run scsi-rescan-bus.sh as root"
+ exit 2
+fi
+[ "$sync" = 1 ] && [ "$remove" = 1 ] && sync=2
+if [ "$sync" = 2 ] ; then
+ echo "Syncing file systems"
+ sync
+fi
+if [ -w /sys/module/scsi_mod/parameters/default_dev_flags ] && [ $scan_flags != 0 ] ; then
+ OLD_SCANFLAGS=$(cat /sys/module/scsi_mod/parameters/default_dev_flags)
+ NEW_SCANFLAGS=$((OLD_SCANFLAGS|scan_flags))
+ if [ "$OLD_SCANFLAGS" != "$NEW_SCANFLAGS" ] ; then
+ echo -n "Temporarily setting kernel scanning flags from "
+ printf "0x%08x to 0x%08x\n" "$OLD_SCANFLAGS" "$NEW_SCANFLAGS"
+ echo $NEW_SCANFLAGS > /sys/module/scsi_mod/parameters/default_dev_flags
+ else
+ unset OLD_SCANFLAGS
+ fi
+fi
+DMSETUP=$(which dmsetup)
+[ -z "$DMSETUP" ] && flush= && mp_enable=
+MULTIPATH=$(which multipath)
+[ -z "$MULTIPATH" ] && flush= && mp_enable=
+
+echo -n "Scanning SCSI subsystem for new devices"
+[ -z "$flush" ] || echo -n ", flush failed multipath devices,"
+[ -z "$remove" ] || echo -n " and remove devices that have disappeared"
+echo
+declare -i found=0
+declare -i updated=0
+declare -i rmvd=0
+
+if [ -n "$flush" ] ; then
+ if [ -x "$MULTIPATH" ] ; then
+ flushmpaths 1
+ fi
+fi
+
+# Update existing mappings
+if [ $update -eq 1 ] ; then
+ echo "Searching for remapped LUNs"
+ findremapped
+ # If you've changed the mapping, there's a chance it's a different size
+ mpaths=""
+ findresized
+# Search for resized LUNs
+elif [ $resize -eq 1 ] ; then
+ echo "Searching for resized LUNs"
+ findresized
+# Normal rescan mode
+else
+ for host in $hosts; do
+ echo -n "Scanning host $host "
+ if [ $no_lip_scan -eq 0 ] && [ -e "/sys/class/fc_host/host$host" ] ; then
+ # It's pointless to do a target scan on FC
+ issue_lip=/sys/class/fc_host/host$host/issue_lip
+ if [ -e "$issue_lip" ] && [ "$lipreset" -ge 0 ] ; then
+ echo 1 > "$issue_lip" 2> /dev/null;
+ udevadm_settle
+ [ "$lipreset" -gt 0 ] && sleep "$lipreset"
+ fi
+ channelsearch=
+ idsearch=
+ else
+ channelsearch=$opt_channelsearch
+ idsearch=$opt_idsearch
+ fi
+ [ -n "$channelsearch" ] && echo -n "channels $channelsearch "
+ echo -n "for "
+ if [ -n "$idsearch" ] ; then
+ echo -n " SCSI target IDs $idsearch"
+ else
+ echo -n " all SCSI target IDs"
+ fi
+ if [ -n "$lunsearch" ] ; then
+ echo ", LUNs $lunsearch"
+ else
+ echo ", all LUNs"
+ fi
+
+ if [ -n "$existing_targets" ] ; then
+ searchexisting
+ else
+ dosearch
+ fi
+ done
+ if [ -n "$OLD_SCANFLAGS" ] ; then
+ echo "$OLD_SCANFLAGS" > /sys/module/scsi_mod/parameters/default_dev_flags
+ fi
+fi
+
+let rmvd_found=$rmvd+$found
+if [ -n "$mp_enable" ] && [ $rmvd_found -gt 0 ] ; then
+ echo "Attempting to update multipath devices..."
+ if [ $rmvd -gt 0 ] ; then
+ udevadm_settle
+ echo "Removing multipath mappings for removed devices if all paths are now failed... "
+ flushmpaths 1
+ fi
+ if [ $found -gt 0 ] ; then
+ /sbin/udevadm trigger --sysname-match=sd*
+ udevadm_settle
+ if [ -x "$MULTIPATH" ] ; then
+ echo "Trying to discover new multipath mappings for newly discovered devices... "
+ $MULTIPATH | grep "create:" 2> /dev/null
+ fi
+ fi
+fi
+
+echo "$found new or changed device(s) found. "
+if [ ! -z "$FOUNDDEVS" ] ; then
+ echo -e "$FOUNDDEVS"
+fi
+echo "$updated remapped or resized device(s) found."
+if [ ! -z "$CHGDEVS" ] ; then
+ echo -e "$CHGDEVS"
+fi
+echo "$rmvd device(s) removed. "
+if [ ! -z "$RMVDDEVS" ] ; then
+ echo -e "$RMVDDEVS"
+fi
+
+# Local Variables:
+# sh-basic-offset: 2
+# End:
+
diff --git a/scripts/scsi-enable-target-scan.sh b/scripts/scsi-enable-target-scan.sh
new file mode 100755
index 00000000..63bb9afb
--- /dev/null
+++ b/scripts/scsi-enable-target-scan.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+MODPARM=/sys/module/scsi_mod/parameters
+if [ -w "$MODPARM/scan" ] ; then
+ scan_type=$(cat $MODPARM/scan)
+ if [ "$scan_type" = "manual" ] ; then
+ echo sync > $MODPARM/scan
+
+ for shost in /sys/class/scsi_host/host* ; do
+ echo '- - -' > ${shost}/scan
+ done
+ fi
+fi
diff --git a/scripts/scsi_logging_level b/scripts/scsi_logging_level
new file mode 100755
index 00000000..2fba2b7f
--- /dev/null
+++ b/scripts/scsi_logging_level
@@ -0,0 +1,268 @@
+#! /bin/bash
+###############################################################################
+# Conveniently create and set scsi logging level, show SCSI_LOG fields in human
+# readable form.
+#
+# (C) Copyright IBM Corp. 2006
+#
+# Modified by D. Gilbert to replace the use of sysctl [20080218]
+# Lat change: D. Gilbert 20150219
+###############################################################################
+
+
+REVISION="1.0"
+SCRIPTNAME="scsi_logging_level"
+
+declare -i LOG_ERROR=0
+declare -i LOG_TIMEOUT=0
+declare -i LOG_SCAN=0
+declare -i LOG_MLQUEUE=0
+declare -i LOG_MLCOMPLETE=0
+declare -i LOG_LLQUEUE=0
+declare -i LOG_LLCOMPLETE=0
+declare -i LOG_HLQUEUE=0
+declare -i LOG_HLCOMPLETE=0
+declare -i LOG_IOCTL=0
+
+declare -i LEVEL=0
+
+SET=0
+GET=0
+CREATE=0
+
+OPTS=$(getopt -o hvcgsa:E:T:S:I:M:L:H: --long \
+help,version,create,get,set,all:,error:,timeout:,scan:,ioctl:,\
+midlevel:,mlqueue:,mlcomplete:,lowlevel:,llqueue:,llcomplete:,\
+highlevel:,hlqueue:,hlcomplete: -n \'$SCRIPTNAME\' -- "$@")
+eval set -- "$OPTS"
+
+# print version info
+printversion()
+{
+ cat <<EOF
+%S390_TOOLS_VERSION% ($SCRIPTNAME $REVISION)
+(C) Copyright IBM Corp. 2006
+EOF
+}
+
+# print usage and help
+printhelp()
+{
+ cat <<EOF
+Usage: $SCRIPTNAME [OPTIONS]
+
+Create, get or set scsi logging level.
+
+Options:
+
+ -h, --help print this help
+ -v, --version print version information
+ -s, --set create and set logging level as specified on
+ command line
+ -g, --get get current logging level and display it
+ -c, --create create logging level as specified on command line
+ -a, --all specify value for all SCSI_LOG fields
+ -E, --error specify SCSI_LOG_ERROR
+ -T, --timeout specify SCSI_LOG_TIMEOUT
+ -S, --scan specify SCSI_LOG_SCAN
+ -M, --midlevel specify SCSI_LOG_MLQUEUE and SCSI_LOG_MLCOMPLETE
+ --mlqueue specify SCSI_LOG_MLQUEUE
+ --mlcomplete specify SCSI_LOG_MLCOMPLETE
+ -L, --lowlevel specify SCSI_LOG_LLQUEUE and SCSI_LOG_LLCOMPLETE
+ --llqueue specify SCSI_LOG_LLQUEUE
+ --llcomplete specify SCSI_LOG_LLCOMPLETE
+ -H, --highlevel specify SCSI_LOG_HLQUEUE and SCSI_LOG_HLCOMPLETE
+ --hlqueue specify SCSI_LOG_HLQUEUE
+ --hlcomplete specify SCSI_LOG_HLCOMPLETE
+ -I, --ioctl specify SCSI_LOG_IOCTL
+
+Exactly one of the options "-c", "-g" and "-s" has to be specified.
+Valid values for SCSI_LOG fields are integers from 0 to 7.
+
+Note: Several SCSI_LOG fields can be specified using several options.
+When multiple options specify same SCSI_LOG field the most specific
+option has precedence.
+
+Example: "scsi_logging_level --hlqueue 3 --highlevel 2 --all 1 -s" sets
+SCSI_LOG_HLQUEUE=3, SCSI_LOG_HLCOMPLETE=2 and assigns all other SCSI_LOG
+fields the value 1.
+EOF
+}
+
+check_level()
+{
+ num=$(($1))
+ if [ $num != "$1" ] ; then
+ invalid_cmdline "log level '$1' not a number"
+ elif [ $num -lt 0 ] || [ $num -gt 7 ] ; then
+ invalid_cmdline "log level '$1' out of range, expect '0' to '7'"
+ fi
+}
+
+# check cmd line arguments
+check_cmdline()
+{
+ while true ; do
+ case "$1" in
+ -a|--all) _ALL="$2"; check_level "$2"
+ shift 2;;
+ -c|--create) CREATE=1;
+ shift 1;;
+ -g|--get) GET=1
+ shift 1;;
+ -h|--help) printhelp
+ exit 0;;
+ -s|--set) SET=1
+ shift 1;;
+ -v|--version) printversion
+ exit 0;;
+ -E|--error) _ERROR="$2"; check_level "$2"
+ shift 2;;
+ -T|--timeout) _TIMEOUT="$2"; check_level "$2"
+ shift 2;;
+ -S|--scan) _SCAN="$2"; check_level "$2"
+ shift 2;;
+ -M|--midlevel) _ML="$2"; check_level "$2"
+ shift 2;;
+ --mlqueue) _MLQUEUE="$2"; check_level "$2"
+ shift 2;;
+ --mlcomplete) _MLCOMPLETE="$2"; check_level "$2"
+ shift 2;;
+ -L|--lowlevel) _LL="$2"; check_level "$2"
+ shift 2;;
+ --llqueue) _LLQUEUE="$2"; check_level "$2"
+ shift 2;;
+ --llcomplete) _LLCOMPLETE="$2"; check_level "$2"
+ shift 2;;
+ -H|--highlevel) _HL="$2"; check_level "$2"
+ shift 2;;
+ --hlqueue) _HLQUEUE="$2"; check_level "$2"
+ shift 2;;
+ --hlcomplete) _HLCOMPLETE="$2"; check_level "$2"
+ shift 2;;
+ -I|--ioctl) _IOCTL="$2"; check_level "$2"
+ shift 2;;
+ --) shift; break;;
+ *) echo "Internal error!" ; exit 1;;
+ esac
+ done
+
+ if [ -n "$*" ]
+ then
+ invalid_cmdline invalid parameter "$@"
+ fi
+
+ if [ $GET = "1" -a $SET = "1" ]
+ then
+ invalid_cmdline options \'-c\', \'-g\' and \'-s\' are mutual exclusive
+ elif [ $GET = "1" -a $CREATE = "1" ]
+ then
+ invalid_cmdline options \'-c\', \'-g\' and \'-s\' are mutual exclusive
+ elif [ $SET = "1" -a $CREATE = "1" ]
+ then
+ invalid_cmdline options \'-c\', \'-g\' and \'-s\' are mutual exclusive
+ fi
+
+ LOG_ERROR=${_ERROR:-${_ALL:-0}}
+ LOG_TIMEOUT=${_TIMEOUT:-${_ALL:-0}}
+ LOG_SCAN=${_SCAN:-${_ALL:-0}}
+ LOG_MLQUEUE=${_MLQUEUE:-${_ML:-${_ALL:-0}}}
+ LOG_MLCOMPLETE=${_MLCOMPLETE:-${_ML:-${_ALL:-0}}}
+ LOG_LLQUEUE=${_LLQUEUE:-${_LL:-${_ALL:-0}}}
+ LOG_LLCOMPLETE=${_LLCOMPLETE:-${_LL:-${_ALL:-0}}}
+ LOG_HLQUEUE=${_HLQUEUE:-${_HL:-${_ALL:-0}}}
+ LOG_HLCOMPLETE=${_HLCOMPLETE:-${_HL:-${_ALL:-0}}}
+ LOG_IOCTL=${_IOCTL:-${_ALL:-0}}
+}
+
+invalid_cmdline()
+{
+ echo "$SCRIPTNAME: $*"
+ echo "$SCRIPTNAME: Try '$SCRIPTNAME --help' for more information."
+ exit 1
+}
+
+get_logging_level()
+{
+ echo "Current scsi logging level:"
+# LEVEL=$(sysctl -n dev.scsi.logging_level)
+ LEVEL=$(cat /proc/sys/dev/scsi/logging_level)
+ if [ $? != 0 ]
+ then
+ echo "$SCRIPTNAME: could not read scsi logging level" \
+ "(kernel probably without SCSI_LOGGING support)"
+ exit 1
+ fi
+}
+
+show_logging_level()
+{
+ echo "/proc/sys/dev/scsi/logging_level = $LEVEL"
+
+ LOG_ERROR=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_TIMEOUT=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_SCAN=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_MLQUEUE=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_MLCOMPLETE=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_LLQUEUE=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_LLCOMPLETE=$((LEVEL & 7)); LEVEL=$((LEVEL>>3))
+ LOG_HLQUEUE=$((LEVEL & 7)); LEVEL=$((LEVEL>>3));
+ LOG_HLCOMPLETE=$((LEVEL & 7)); LEVEL=$((LEVEL>>3));
+ LOG_IOCTL=$((LEVEL & 7))
+
+ echo "SCSI_LOG_ERROR=$LOG_ERROR"
+ echo "SCSI_LOG_TIMEOUT=$LOG_TIMEOUT"
+ echo "SCSI_LOG_SCAN=$LOG_SCAN"
+ echo "SCSI_LOG_MLQUEUE=$LOG_MLQUEUE"
+ echo "SCSI_LOG_MLCOMPLETE=$LOG_MLCOMPLETE"
+ echo "SCSI_LOG_LLQUEUE=$LOG_LLQUEUE"
+ echo "SCSI_LOG_LLCOMPLETE=$LOG_LLCOMPLETE"
+ echo "SCSI_LOG_HLQUEUE=$LOG_HLQUEUE"
+ echo "SCSI_LOG_HLCOMPLETE=$LOG_HLCOMPLETE"
+ echo "SCSI_LOG_IOCTL=$LOG_IOCTL"
+}
+
+set_logging_level()
+{
+ echo "New scsi logging level:"
+# sysctl -q -w dev.scsi.logging_level=$LEVEL
+ echo $LEVEL > /proc/sys/dev/scsi/logging_level
+ if [ $? != 0 ]
+ then
+ echo "$SCRIPTNAME: could not write scsi logging level $LEVEL"
+ echo " kernel does not have SCSI_LOGGING support or needs superuser"
+ exit 1
+ fi
+}
+create_logging_level()
+{
+ LEVEL=$((LOG_IOCTL & 7)); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_HLCOMPLETE & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_HLQUEUE & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_LLCOMPLETE & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_LLQUEUE & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_MLCOMPLETE & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_MLQUEUE & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_SCAN & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_TIMEOUT & 7))); LEVEL=$((LEVEL<<3))
+ LEVEL=$((LEVEL|(LOG_ERROR & 7)))
+}
+
+check_cmdline "$@"
+
+if [ $SET = "1" ]
+then
+ create_logging_level
+ set_logging_level
+ show_logging_level
+elif [ $GET = "1" ]
+then
+ get_logging_level
+ show_logging_level
+elif [ $CREATE = "1" ]
+then
+ create_logging_level
+ show_logging_level
+else
+ invalid_cmdline missing option \'-g\', \'-s\' or \'-c\'
+fi
diff --git a/scripts/scsi_mandat b/scripts/scsi_mandat
new file mode 100755
index 00000000..1f72b406
--- /dev/null
+++ b/scripts/scsi_mandat
@@ -0,0 +1,133 @@
+#!/bin/bash
+# scsi_mandat
+#
+# Script to test compliance with SCSI mandatory commands.
+# The vintage is SPC-3 and SPC-4 (see www.t10.org).
+#
+# Coverage:
+# Command Standard/Draft (is mandatory in)
+# -------------------------------------------------------
+# INQUIRY (standard) SCSI-2, SPC, SPC-2, SPC-3, SPC-4
+# INQUIRY (VPD pages 0, 0x83) SPC-2, SPC-3, SPC-4
+# REPORT LUNS SPC-3, SPC-4
+# TEST UNIT READY SCSI-2, SPC, SPC-2, SPC-3, SPC-4
+# REQUEST SENSE SCSI-2, SBC, SBC-2,3, MMC-4,5, SSC-2,3
+# SEND DIAGNOSTIC SBC, SBC-2,3, SSC-2,3
+#
+# This script uses utilities frim sg3_utils package (version
+# 1.21 or later)
+#
+# Douglas Gilbert 20131016
+
+
+log=0
+quiet=0
+verbose=""
+
+file_err=0
+inv_opcode=0
+illeg_req=0
+not_ready=0
+medium=0
+other_err=0
+recovered=0
+sanity=0
+syntax=0
+timeout=0
+unit_attention=0
+aborted_command=0
+
+## total_err=0
+
+usage()
+{
+ echo "Usage: scsi_mandat [-h] [-L] [-q] [-v] <device>"
+ echo " where: -h, --help print usage message"
+ echo " -L, --log append stderr to 'scsi_mandat.err'"
+ echo " -q, --quiet suppress some output"
+ echo " -v, --verbose increase verbosity of output"
+ echo ""
+ echo "Check <device> for mandatory SCSI command support"
+}
+
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ h|-help) usage ; exit 0 ;;
+ L|-log) let log=$log+1 ;;
+ q|-quiet) let quiet=$quiet+1 ;;
+ v|-verbose) verbose="-v" ;;
+ vv) verbose="-vv" ;;
+ vvv) verbose="-vvv" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for command in "sg_inq" "sg_luns" "sg_turs" "sg_requests" "sg_vpd" \
+ "sg_vpd -i" "sg_senddiag -t"
+do
+ if [ $quiet -eq 0 ]
+ then echo "$command" $verbose "$1"
+ fi
+
+ if [ $verbose ]
+ then
+ if [ $log -eq 0 ]
+ then
+ $command $verbose "$1"
+ else
+ $command $verbose "$1" >> scsi_mandat.err 2>> scsi_mandat.err
+ fi
+ else
+ if [ $log -eq 0 ]
+ then
+ $command "$1" > /dev/null 2>> /dev/null
+ else
+ $command "$1" > /dev/null 2>> scsi_mandat.err
+ fi
+ fi
+ res=$?
+ case "$res" in
+ 0) ;;
+ 1) echo " syntax error" ; let syntax=$syntax+1 ;;
+ 2) echo " not ready" ; let not_ready=$not_ready+1 ;;
+ 3) echo " medium error" ; let medium=$medium+1 ;;
+ 5) echo " illegal request, general" ; let illeg_req=$illeg_req+1 ;;
+ 6) echo " unit attention" ; let unit_attention=$unit_attention+1 ;;
+ 9) echo " illegal request, invalid opcode" ; let inv_opcode=$inv_opcode+1 ;;
+ 11) echo " aborted command" ; let aborted_command=$aborted_command+1 ;;
+ 15) echo " file error with $1 " ; let file_err=$file_err+1 ;;
+ 20) echo " no sense" ; let other_err=$other_err+1 ;;
+ 21) echo " recovered error" ; let recovered=$recovered+1 ;;
+ 33) echo " timeout" ; let timeout=$timeout+1 ;;
+ 97) echo " response fails sanity" ; let sanity=$sanity+1 ;;
+ 98) echo " other SCSI error" ; let other_err=$other_err+1 ;;
+ 99) echo " other error" ; let other_err=$other_err+1 ;;
+ *) echo " unknown exit status for sg_inq: $res" ; let other_err=$other_err+1 ;;
+ esac
+done
+
+echo ""
+let total_bad_err=$file_err+$inv_opcode+$illeg_req+$medium+$aborted_command
+let total_bad_err+=$other_err+$recovered+$sanity+$syntax+$timeout
+
+let total_allow_err=$not_ready+$unit_attention
+
+ echo "total number of bad errors: $total_bad_err "
+
+if [ $total_allow_err -gt 0 ]
+ then
+ echo "total number of allowable errors: $total_allow_err "
+fi
+
+exit $total_bad_err
diff --git a/scripts/scsi_readcap b/scripts/scsi_readcap
new file mode 100755
index 00000000..8f308f4f
--- /dev/null
+++ b/scripts/scsi_readcap
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+###################################################################
+#
+# Fetch READ CAPACITY information for the given SCSI device(s).
+#
+# This script assumes the sg3_utils package is installed.
+#
+##################################################################
+
+verbose=""
+brief=""
+long_opt=""
+
+usage()
+{
+ echo "Usage: scsi_readcap [-b] [-h] [-l] [-v] <device>+"
+ echo " where:"
+ echo " -b, --brief output brief capacity data"
+ echo " -h, --help print usage message"
+ echo " -l, --long send longer SCSI READ CAPACITY (16) cdb"
+ echo " -v, --verbose more verbose output"
+ echo ""
+ echo "Use SCSI READ CAPACITY command to fetch the size of each <device>"
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ b|-brief) brief="-b" ;;
+ h|-help) usage ; exit 0 ;;
+ l|-long) long_opt="--16" ;;
+ v|-verbose) verbose="-v" ;;
+ vv) verbose="-vv" ;;
+ vvv) verbose="-vvv" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for i
+do
+ if [ $brief ] ; then
+ sg_readcap $brief $long_opt $verbose $i 2> /dev/null
+ else
+ echo "sg_readcap $brief $long_opt $verbose $i"
+ sg_readcap $brief $long_opt $verbose $i
+ fi
+done
diff --git a/scripts/scsi_ready b/scripts/scsi_ready
new file mode 100755
index 00000000..724c2c63
--- /dev/null
+++ b/scripts/scsi_ready
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+################################################
+#
+# Send a TEST UNIT READY SCSI command to each given device.
+#
+# This script assumes the sg3_utils package is installed and uses
+# the sg_turs utility..
+#
+###############################################
+
+verbose=""
+brief=""
+
+usage()
+{
+ echo "Usage: scsi_ready [-b] [-h] [-v] <device>+"
+ echo " where:"
+ echo " -b, --brief print 'ready' or 'device not ready' only"
+ echo " -h, --help print usage message"
+ echo " -v, --verbose more verbose output"
+ echo ""
+ echo "Send SCSI TEST UNIT READY to each <device>"
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ b|-brief) brief="1" ;;
+ h|-help) usage ; exit 0 ;;
+ v|-verbose) verbose="-v" ;;
+ vv) verbose="-vv" ;;
+ vvv) verbose="-vvv" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for i
+do
+ if [ ! $brief ] ; then
+ echo "sg_turs $verbose $i"
+ fi
+ echo -n " "
+ if sg_turs $verbose $i ; then
+ echo "ready"
+ fi
+done
diff --git a/scripts/scsi_satl b/scripts/scsi_satl
new file mode 100755
index 00000000..08042ae3
--- /dev/null
+++ b/scripts/scsi_satl
@@ -0,0 +1,134 @@
+#!/bin/bash
+# scsi_satl
+#
+# Script to test compliance of SCSI commands on a SCSI to ATA
+# Translation (SAT) Layer (SATL). This script was compiled using
+# sat-r09.pdf found at www.t10.org .
+# The scripts still seems to be valid for sat2r09.pdf .
+# The vintage is SPC-3 and SPC-4 (see www.t10.org).
+#
+# Coverage:
+# Command SATL notes
+# -------------------------------------------------------
+# INQUIRY (standard)
+# INQUIRY (VPD: 0)
+# INQUIRY (VPD: 0x83) Device identification VPD page
+# INQUIRY (VPD: 0x89) ATA Information VPD page
+# REPORT LUNS SPC-3, SPC-4 (hardly mentioned in sat-r08c)
+# TEST UNIT READY
+# REQUEST SENSE
+# SEND DIAGNOSTIC default self test
+# MODE SENSE(10) draft unclear which mode pages, so ask for all
+# ATA PASS THROUGH(16) send IDENTIFY DEVICE command. Assume non-packet
+# device, if packet device add "-p" option
+#
+# This script uses utilities from sg3_utils package (version
+# 1.22 or later)
+#
+# Douglas Gilbert 20090930
+
+
+log=0
+quiet=0
+verbose=""
+
+file_err=0
+inv_opcode=0
+illeg_req=0
+not_ready=0
+medium=0
+other_err=0
+recovered=0
+sanity=0
+syntax=0
+timeout=0
+unit_attention=0
+aborted_command=0
+
+## total_err=0
+
+usage()
+{
+ echo "Usage: scsi_satl [-h] [-L] [-q] [-v] <device>"
+ echo " where: -h, --help print usage message"
+ echo " -L, --log append stderr to 'scsi_satl.err'"
+ echo " -q, --quiet suppress some output"
+ echo " -v, --verbose more verbose output"
+ echo ""
+ echo "Check <device> for SCSI to ATA Translation Layer (SATL) support"
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ h|-help) usage ; exit 1 ;;
+ L|-log) let log=$log+1 ;;
+ q|-quiet) let quiet=$quiet+1 ;;
+ v|-verbose) verbose="-v" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for command in "sg_inq" "sg_vpd" "sg_vpd -p di" "sg_vpd -p ai" "sg_luns" \
+ "sg_turs" "sg_requests -s" "sg_senddiag -t" "sg_modes -a" \
+ "sg_sat_identify"
+do
+ if [ $quiet -eq 0 ]
+ then echo "$command" "$1"
+ fi
+
+ if [ $log -eq 0 ]
+ then
+ if [ $verbose ]
+ then
+ $command $verbose "$1" > /dev/null
+ else
+ $command "$1" > /dev/null 2>> /dev/null
+ fi
+ else
+ $command $verbose "$1" > /dev/null 2>> scsi_satl.err
+ fi
+ res=$?
+ case "$res" in
+ 0) ;;
+ 1) echo " syntax error" ; let syntax=$syntax+1 ;;
+ 2) echo " not ready" ; let not_ready=$not_ready+1 ;;
+ 3) echo " medium error" ; let medium=$medium+1 ;;
+ 5) echo " illegal request, general" ; let illeg_req=$illeg_req+1 ;;
+ 6) echo " unit attention" ; let unit_attention=$unit_attention+1 ;;
+ 9) echo " illegal request, invalid opcode" ; let inv_opcode=$inv_opcode+1 ;;
+ 11) echo " aborted command" ; let aborted_command=$aborted_command+1 ;;
+ 15) echo " file error with $1 " ; let file_err=$file_err+1 ;;
+ 20) echo " no sense" ; let other_err=$other_err+1 ;;
+ 21) echo " recovered error" ; let recovered=$recovered+1 ;;
+ 33) echo " timeout" ; let timeout=$timeout+1 ;;
+ 97) echo " response fails sanity" ; let sanity=$sanity+1 ;;
+ 98) echo " other SCSI error" ; let other_err=$other_err+1 ;;
+ 99) echo " other error" ; let other_err=$other_err+1 ;;
+ *) echo " unknown exit status for sg_inq: $res" ; let other_err=$other_err+1 ;;
+ esac
+done
+
+echo ""
+let total_bad_err=$file_err+$inv_opcode+$illeg_req+$medium+$aborted_command
+let total_bad_err+=$other_err+$recovered+$sanity+$syntax+$timeout
+
+let total_allow_err=$not_ready+$unit_attention
+
+ echo "total number of bad errors: $total_bad_err "
+
+if [ $total_allow_err -gt 0 ]
+ then
+ echo "total number of allowable errors: $total_allow_err "
+fi
+
+exit $total_bad_err
diff --git a/scripts/scsi_start b/scripts/scsi_start
new file mode 100755
index 00000000..aec7ab97
--- /dev/null
+++ b/scripts/scsi_start
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+################################################
+#
+# Spin up the given SCSI disk(s).
+#
+# SCSI disks (or disks that understand SCSI commands)
+# are assumed. By default, the immediate bit is set so the
+# command should return immediately. The disk however will
+# take 10 seconds or more to spin up. The '-w' option
+# causes each start to wait until the disk reports that it
+# has started.
+#
+# This script assumes the sg3_utils package is installed.
+#
+###############################################
+
+verbose=""
+immediate="-i"
+
+usage()
+{
+ echo "Usage: scsi_start [-h] [-v] [-w] <device>+"
+ echo " where:"
+ echo " -h, --help print usage message"
+ echo " -v, --verbose more verbose output"
+ echo " -w, --wait wait for each start to complete"
+ echo ""
+ echo "Send SCSI START STOP UNIT command to start each <device>"
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ h|-help) usage ; exit 0 ;;
+ v|-verbose) verbose="-v" ;;
+ w|-wait) immediate="" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for i
+do
+ echo "sg_start $immediate 1 $verbose $i"
+ sg_start $immediate 1 $verbose $i
+done
diff --git a/scripts/scsi_stop b/scripts/scsi_stop
new file mode 100755
index 00000000..76807234
--- /dev/null
+++ b/scripts/scsi_stop
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+################################################
+#
+# Spin down the given SCS disk(s).
+#
+# SCSI disks (or disks that understand SCSI commands)
+# are assumed. By default, the immediate bit is set so the
+# command should return immediately. The disk however will
+# take 10 seconds or more to spin down. The '-w' option
+# causes each stop to wait until the disk reports that it
+# has stopped.
+#
+# This script assumes the sg3_utils package is installed.
+#
+###############################################
+
+verbose=""
+immediate="-i"
+
+usage()
+{
+ echo "Usage: scsi_stop [-h] [-v] [-w] <device>+"
+ echo " where:"
+ echo " -h, --help print usage message"
+ echo " -v, --verbose more verbose output"
+ echo " -w, --wait wait for each stop to complete"
+ echo ""
+ echo "Send SCSI START STOP UNIT command to stop each <device>"
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ h|-help) usage ; exit 0 ;;
+ v|-verbose) verbose="-v" ;;
+ w|-wait) immediate="" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for i
+do
+# Use '-r' (read-only) otherwise using a block device node
+# (e.g. 'sg_start 0 /dev/sdb') can result in a change of state
+# event causing the disk to spin up again immediately.
+ echo "sg_start -r $immediate 0 $verbose $i"
+ sg_start -r $immediate 0 $verbose $i
+done
diff --git a/scripts/scsi_temperature b/scripts/scsi_temperature
new file mode 100755
index 00000000..f7d041cd
--- /dev/null
+++ b/scripts/scsi_temperature
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+###################################################################
+#
+# Check the temperature of the given SCSI device(s).
+#
+# This script assumes the sg3_utils package is installed.
+#
+##################################################################
+
+verbose=""
+
+usage()
+{
+ echo "Usage: scsi_temperature [-h] [-v] <device>+"
+ echo " where:"
+ echo " -h, --help print usage message"
+ echo " -v, --verbose more verbose output"
+ echo ""
+ echo "Use SCSI LOG SENSE command to fetch temperature of each <device>"
+}
+
+opt="$1"
+while test ! -z "$opt" -a -z "${opt##-*}"; do
+ opt=${opt#-}
+ case "$opt" in
+ h|-help) usage ; exit 0 ;;
+ v|-verbose) verbose="-v" ;;
+ vv) verbose="-vv" ;;
+ *) echo "Unknown option: -$opt " ; exit 1 ;;
+ esac
+ shift
+ opt="$1"
+done
+
+if [ $# -lt 1 ]
+ then
+ usage
+ exit 1
+fi
+
+for i
+do
+ echo "sg_logs -t $verbose $i"
+ sg_logs -t $verbose $i
+done