diff options
author | Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com> | 2023-09-13 10:52:49 +0900 |
---|---|---|
committer | Vincent Fu <vincent.fu@samsung.com> | 2023-09-26 09:00:13 -0400 |
commit | 996ac91f54844e63ef43092472fc1f7610567b67 (patch) | |
tree | 3f48313af8a82faa9351e8f3c926aaf991b2ff67 | |
parent | a142e0df6c1483a76d92ff7f9d8c07242af9910e (diff) | |
download | fio-996ac91f54844e63ef43092472fc1f7610567b67.tar.gz |
t/zbd: set mq-deadline scheduler to device-mapper destination devices
When write workloads run on zoned block devices, mq-deadline scheduler is
required to ensure write operations are sequential. To fulfill this
requirement, the test script t/zbd/test-zbd-support sets mq-deadline to
the sysfs attribute "queue/scheduler". However, this preparation does
not work when the write target device is a bio based device-mapper
device. The device is bio based then I/O scheduler does not work.
Setting mq-deadline to the sysfs attribute has no effect. On top of
that, the sysfs attribute "queue/scheduler" is no longer available for
bio based device-mapper devices since Linux kernel version v6.5.
To ensure mq-deadline scheduler for bio based device-mapper devices,
improve the helper function set_io_scheduler. If the sysfs attribute
"queue/scheduler" is available, use it. Otherwise, check if the test
device is a zoned device-mapper (linear, flakey or crypt). If so, set
mq-deadline scheduler to destination devices of the device-mapper
device. To implement these, add some helper functions.
Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
Link: https://lore.kernel.org/r/20230913015249.2226799-1-shinichiro.kawasaki@wdc.com
Signed-off-by: Vincent Fu <vincent.fu@samsung.com>
-rw-r--r-- | t/zbd/functions | 11 | ||||
-rwxr-xr-x | t/zbd/test-zbd-support | 61 |
2 files changed, 71 insertions, 1 deletions
diff --git a/t/zbd/functions b/t/zbd/functions index 4faa45a92..028df4040 100644 --- a/t/zbd/functions +++ b/t/zbd/functions @@ -27,6 +27,17 @@ blkzone_reports_capacity() { "${blkzone}" report -c 1 -o 0 "${dev}" | grep -q 'cap ' } +has_command() { + local cmd="${1}" + + cmd_path=$(type -p "${cmd}" 2>/dev/null) + if [ -z "${cmd_path}" ]; then + echo "${cmd} is not available" + return 1 + fi + return 0 +} + # Whether or not $1 (/dev/...) is a NVME ZNS device. is_nvme_zns() { local s diff --git a/t/zbd/test-zbd-support b/t/zbd/test-zbd-support index c8f3eb614..0436d319d 100755 --- a/t/zbd/test-zbd-support +++ b/t/zbd/test-zbd-support @@ -46,6 +46,55 @@ ioengine() { fi } +get_dev_path_by_id() { + for d in /sys/block/* /sys/block/*/*; do + if [[ ! -r "${d}/dev" ]]; then + continue + fi + if [[ "${1}" == "$(<"${d}/dev")" ]]; then + echo "/dev/${d##*/}" + return 0 + fi + done + return 1 +} + +dm_destination_dev_set_io_scheduler() { + local dev=$1 sched=$2 + local dest_dev_id dest_dev path + + has_command dmsetup || return 1 + + while read -r dest_dev_id; do + if ! dest_dev=$(get_dev_path_by_id "${dest_dev_id}"); then + continue + fi + path=${dest_dev/dev/sys\/block}/queue/scheduler + if [[ ! -w ${path} ]]; then + echo "Can not set scheduler of device mapper destination: ${dest_dev}" + continue + fi + echo "${2}" > "${path}" + done < <(dmsetup table "$(<"/sys/block/$dev/dm/name")" | + sed -n 's/.* \([0-9]*:[0-9]*\).*/\1/p') +} + +dev_has_dm_map() { + local dev=${1} target_type=${2} + local dm_name + + has_command dmsetup || return 1 + + dm_name=$(<"/sys/block/$dev/dm/name") + if ! dmsetup status "${dm_name}" | grep -qe "${target_type}"; then + return 1 + fi + if dmsetup status "${dm_name}" | grep -v "${target_type}"; then + return 1 + fi + return 0 +} + set_io_scheduler() { local dev=$1 sched=$2 @@ -62,7 +111,17 @@ set_io_scheduler() { esac fi - echo "$sched" >"/sys/block/$dev/queue/scheduler" + if [ -w "/sys/block/$dev/queue/scheduler" ]; then + echo "$sched" >"/sys/block/$dev/queue/scheduler" + elif [ -r "/sys/block/$dev/dm/name" ] && + ( dev_has_dm_map "$dev" linear || + dev_has_dm_map "$dev" flakey || + dev_has_dm_map "$dev" crypt ); then + dm_destination_dev_set_io_scheduler "$dev" "$sched" + else + echo "can not set io scheduler" + exit 1 + fi } check_read() { |