diff mbox series

[blktests,v2,4/6] common/scsi_debug: introduce _configure_scsi_debug

Message ID 20230425114745.376322-5-shinichiro@fastmail.com
State New
Headers show
Series [blktests,v2,1/6] common/rc: skip module file check if modules path does not exist | expand

Commit Message

Shin'ichiro Kawasaki April 25, 2023, 11:47 a.m. UTC
From: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>

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 find sysfs files corresponding to the keys in
/sys/bus/pseudo/drivers/scsi_debug or /sys/module/scsi_debug/parameters.
When the file is found, write the value to the file.

Before setting the parameters through sysfs files, save current values
of scsi_debug parameters in ORIG_SCSI_DEBUG_PARAMS. Use the saved values
to restore parameters in _exit_scsi_debug. Do this value restore not
only for the parameters modified in _configure_scsi_debug but also for
the parameters modified by test cases.

Among the parameters, 'add_host' has special meaning to add new hosts.
Then handle it 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@wdc.com>
---
 common/scsi_debug | 112 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 111 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/common/scsi_debug b/common/scsi_debug
index 0bf768a..3d83d8a 100644
--- a/common/scsi_debug
+++ b/common/scsi_debug
@@ -8,16 +8,51 @@  _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
+declare -A ORIG_SCSI_DEBUG_PARAMS
+declare SCSI_DEBUG_ADD_HOST_RESTORE_VALUE
+
 _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 +94,85 @@  _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[@]}")
+
+	# Save current values of all scsi_debug parameters except add_host
+	ORIG_SCSI_DEBUG_PARAMS=()
+	for path in "$SD_PSEUDO_PATH"/* "$SD_PARAM_PATH"/*; do
+		if [[ -f $path && ! $path =~ add_host ]] &&
+			   [[ $(stat -c "%A" "$path") =~ rw ]]; then
+			ORIG_SCSI_DEBUG_PARAMS["$path"]="$(<"$path")"
+		fi
+	done
+
+	# Modify parameters specifeid with key=value arguments
+	for o in "$@"; do
+		key=${o%=*}
+		value=${o#*=}
+		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
+			add_host_value=${value}
+		else
+			echo "restore $path" >> /tmp/debug
+			echo -n "$value" > "$path"
+		fi
+	done
+
+	echo "${add_host_value}" > ${SD_PSEUDO_PATH}/add_host
+	SCSI_DEBUG_ADD_HOST_RESTORE_VALUE="-${add_host_value}"
+
+	udevadm settle
+
+	_setup_scsi_debug_vars
+}
+
 _exit_scsi_debug() {
+	local path value
+
 	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
+
+	echo "${SCSI_DEBUG_ADD_HOST_RESTORE_VALUE}" > ${SD_PSEUDO_PATH}/add_host
+
+	# Restore parameters modified in _configure_scsi_debug or during test
+	for path in "${!ORIG_SCSI_DEBUG_PARAMS[@]}"; do
+		value=${ORIG_SCSI_DEBUG_PARAMS[$path]}
+		if [[ "$value" != $(<"$path") ]]; then
+			echo -n "$value" > "$path"
+		fi
+	done
+	unset ORIG_SCSI_DEBUG_PARAMS
 }