From: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx> To set up scsi_debug devices with built-in scsi_debug module, introduce a new helper function _configure_scsi_debug. It works in similar manner as _init_scsi_debug which sets up scsi_debug devices with loadable scsi_debug module. _configure_scsi_debug takes parameters of scsi_debug devices in format of 'key=value' as its arguments. It calls another new helper function _scsi_debug_key_path to search sysfs files corresponding to the keys in /sys/bus/pseudo/drivers/scsi_debug or /sys/module/scsi_debug/parameters. When it finds the file, it writes the value to the file. The original values of the files are kept in the global array SCSI_DEBUG_VALUES and restored by _exit_scsi_debug. Among the parameters, 'add_host' has special meaning to add new hosts. Then it is handled separately so that it is set at last in _configure_scsi_debug, and restored at first in _exit_scsi_debug. Also, record the hosts which exist before _configure_scsi_debug in the array ORIG_SCSI_DEBUG_HOSTS. Those hosts should not be used for testing, then do not add them to SCSI_DEBUG_HOSTS. Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx> --- common/scsi_debug | 113 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/common/scsi_debug b/common/scsi_debug index 0bf768a..ee9edac 100644 --- a/common/scsi_debug +++ b/common/scsi_debug @@ -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 } -- 2.39.2