@@ -8,16 +8,49 @@ _have_scsi_debug() {
_have_driver scsi_debug
}
+SD_PSEUDO_PATH=/sys/bus/pseudo/drivers/scsi_debug
+SD_PARAM_PATH=/sys/module/scsi_debug/parameters
+
+_scsi_debug_key_path() {
+ local key=${1}
+
+ path="${SD_PSEUDO_PATH}/$key"
+ if [[ ! -e $path ]]; then
+ path="${SD_PARAM_PATH}/$key"
+ fi
+ if [[ ! -w $path ]]; then
+ return 1
+ fi
+
+ echo "$path"
+}
+
+declare -a SCSI_DEBUG_HOSTS
+declare -a SCSI_DEBUG_TARGETS
+declare -a SCSI_DEBUG_DEVICES
+declare -a ORIG_SCSI_DEBUG_HOSTS
+
_setup_scsi_debug_vars() {
local host_sysfs host target_sysfs target
+ local -i i
+
SCSI_DEBUG_HOSTS=()
SCSI_DEBUG_TARGETS=()
SCSI_DEBUG_DEVICES=()
+
for host_sysfs in /sys/class/scsi_host/*; do
if [[ "$(cat "${host_sysfs}/proc_name")" = scsi_debug ]]; then
host="${host_sysfs#/sys/class/scsi_host/host}"
+ local orig_host=0
+ for ((i=0;i<${#ORIG_SCSI_DEBUG_HOSTS[@]};i++)); do
+ if (( host == ORIG_SCSI_DEBUG_HOSTS[i])); then
+ orig_host=1
+ fi
+ done
+ ((orig_host)) && continue
SCSI_DEBUG_HOSTS+=("$host")
for target_sysfs in /sys/class/scsi_device/"$host":*; do
+ [[ ! -e $target_sysfs ]] && break
target="${target_sysfs#/sys/class/scsi_device/}"
SCSI_DEBUG_TARGETS+=("$target")
SCSI_DEBUG_DEVICES+=("$(ls "$target_sysfs/device/block")")
@@ -59,10 +92,88 @@ _init_scsi_debug() {
_setup_scsi_debug_vars
}
+_configure_scsi_debug() {
+ local -a args=("$@")
+ local -a values
+ local key value path add_host_value=1
+ local -i i
+
+ udevadm settle
+
+ # fall back to _init_scsi_debug because scsi_debug is loadable
+ if _module_file_exists scsi_debug; then
+ _init_scsi_debug "${args[@]}"
+ return
+ fi
+
+ # zoned device is not yet configurable due to read-only zbc parameter
+ if (( RUN_FOR_ZONED )) && ! _have_module scsi_debug; then
+ return 1
+ fi
+
+ # List SCSI_DEBUG_HOSTS before configuration
+ ORIG_SCSI_DEBUG_HOSTS=()
+ _setup_scsi_debug_vars >& /dev/null
+ ORIG_SCSI_DEBUG_HOSTS=("${SCSI_DEBUG_HOSTS[@]}")
+
+ SCSI_DEBUG_KEYS=()
+ SCSI_DEBUG_VALUES=()
+ for o in "$@"; do
+ key=${o%=*}
+ value=${o#*=}
+ SCSI_DEBUG_KEYS+=("${key}")
+ values+=("${value}")
+ if ! path=$(_scsi_debug_key_path "${key}"); then
+ echo "sysfs to write $key is not avaialbe"
+ return 1
+ fi
+ if [[ $key == add_host ]]; then
+ SCSI_DEBUG_VALUES+=("-${value}")
+ add_host_value=${value}
+ else
+ SCSI_DEBUG_VALUES+=("$(<"${path}")")
+ echo -n "${value}" > "${path}"
+ fi
+ done
+
+ echo "${add_host_value}" > ${SD_PSEUDO_PATH}/add_host
+
+ udevadm settle
+
+ _setup_scsi_debug_vars
+}
+
_exit_scsi_debug() {
+ local i key path add_host_value=-1
+
unset SCSI_DEBUG_HOSTS
unset SCSI_DEBUG_TARGETS
unset SCSI_DEBUG_DEVICES
udevadm settle
- modprobe -r scsi_debug
+
+ if _module_file_exists scsi_debug; then
+ modprobe -r scsi_debug
+ return
+ fi
+
+ for ((i = 0; i < ${#SCSI_DEBUG_KEYS[@]}; i++)); do
+ key=${SCSI_DEBUG_KEYS[i]}
+ if [[ $key == add_host ]]; then
+ add_host_value=${SCSI_DEBUG_VALUES[i]}
+ fi
+ done
+ echo "${add_host_value}" > ${SD_PSEUDO_PATH}/add_host
+
+ for ((i = 0; i < ${#SCSI_DEBUG_KEYS[@]}; i++)); do
+ key=${SCSI_DEBUG_KEYS[i]}
+ if ! path=$(_scsi_debug_key_path "${key}"); then
+ echo "sysfs to write $key is not avaialbe"
+ return 1
+ fi
+ if [[ $key != add_host ]]; then
+ echo -n "${SCSI_DEBUG_VALUES[i]}" > "${path}"
+ fi
+ done
+ unset SCSI_DEBUG_KEYS
+ unset SCSI_DEBUG_VALUES
}