diff --git a/common/multipath-over-rdma b/common/multipath-over-rdma index 1084f80a..3d392d79 100644 --- a/common/multipath-over-rdma +++ b/common/multipath-over-rdma @@ -156,7 +156,7 @@ dev_to_mpath() { [ -e "$1" ] || return $? if [ -L "$1" ]; then - e=$(readlink -f "$1") + e=$(readlink --canonicalize "$1") else e="$1" fi @@ -167,7 +167,7 @@ dev_to_mpath() { for d in /dev/mapper/mpath*; do if [ -L "$d" ]; then - e=$(readlink -f "$d") + e=$(readlink --canonicalize "$d") elif [ -e "$d" ]; then e="$d" else @@ -240,7 +240,7 @@ remove_mpath_dev() { break fi ls -l "$1" - stop_bdev_users "$(readlink -f "$1")" + stop_bdev_users "$(readlink --canonicalize "$1")" sleep .5 done if [[ $i = 0 ]]; then diff --git a/common/nvme b/common/nvme index eed5db0a..8a7dd897 100644 --- a/common/nvme +++ b/common/nvme @@ -1122,7 +1122,7 @@ _nvmet_target_cleanup() { } _require_test_dev_is_nvme() { - if ! readlink -f "$TEST_DEV_SYSFS/device" | grep -q nvme; then + if ! readlink --canonicalize "$TEST_DEV_SYSFS/device" | grep -q nvme; then SKIP_REASONS+=("$TEST_DEV is not a NVMe device") return 1 fi diff --git a/common/rc b/common/rc index b76a8568..41b7ce25 100644 --- a/common/rc +++ b/common/rc @@ -392,16 +392,16 @@ _test_dev_set_scheduler() { } _require_test_dev_is_pci() { - if ! readlink -f "$TEST_DEV_SYSFS/device" | grep -q pci; then + if ! readlink --canonicalize "$TEST_DEV_SYSFS/device" | grep -q pci; then # nvme needs some special casing - if readlink -f "$TEST_DEV_SYSFS/device" | grep -q nvme; then + if readlink --canonicalize "$TEST_DEV_SYSFS/device" | grep -q nvme; then local blkdev local ctrldev # First get the controller device from the namespace blockdev blkdev="$(echo "$TEST_DEV_SYSFS" | cut -d '/' -f 7)" ctrldev="$(echo "$blkdev" | grep -Eo 'nvme[0-9]+')" # Then get the pci device from the controller device - if readlink -f "$ctrldev/device" | grep -1 pci; then + if readlink --canonicalize "$ctrldev/device" | grep -1 pci; then return 0 fi fi @@ -413,7 +413,7 @@ _require_test_dev_is_pci() { } _get_pci_from_dev_sysfs() { - readlink -f "$1/device" | \ + readlink --canonicalize "$1/device" | \ grep -Eo '[0-9a-f]{4,5}:[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]' | \ tail -1 } @@ -423,7 +423,7 @@ _get_pci_dev_from_blkdev() { } _get_pci_parent_from_blkdev() { - readlink -f "$TEST_DEV_SYSFS/device" | \ + readlink --canonicalize "$TEST_DEV_SYSFS/device" | \ grep -Eo '[0-9a-f]{4,5}:[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]' | \ tail -2 | head -1 } @@ -734,7 +734,7 @@ _real_dev() { local dev=$1 if [ -b "$dev" ] && [ -L "$dev" ]; then - dev=$(readlink -f "$dev") + dev=$(readlink --canonicalize "$dev") fi echo "$dev" } diff --git a/tests/nvme/050 b/tests/nvme/050 index 91f35642..23150472 100755 --- a/tests/nvme/050 +++ b/tests/nvme/050 @@ -20,13 +20,11 @@ requires() { } test_device() { - local nvme_ns - local pdev - local i + local nvme_ns pdev io_error i echo "Running ${TEST_NAME}" - pdev=$(_get_pci_dev_from_blkdev) + pdev=$(_nvme_get_pci_from_dev_sysfs) nvme_ns="$(basename "${TEST_DEV}")" echo 1 > /sys/block/"${nvme_ns}"/io-timeout-fail @@ -40,10 +38,19 @@ test_device() { --name=reads --direct=1 --filename="${TEST_DEV}" --group_reporting \ --time_based --runtime=1m >& "$FULL" - if grep -q "Input/output error" "$FULL"; then - echo "Test complete" + io_error=false + grep -q "Input/output error" "$FULL" && io_error=true + + # The timeout failure injection causes an I/O to fail immediately. For + # a single-path device, the failed I/O is propagated up the stack and + # eventually reported to user space as an error. For multipath devices, + # the block layer evaluates whether the I/O is eligible for retry via + # failover to an alternate path. Because the I/O fails before the + # per-I/O timeout expires, it remains eligible for retry. + if _nvme_dev_support_native_multipath; then + $io_error && echo "Test failed" || echo "Test complete" else - echo "Test failed" + $io_error && echo "Test complete" || echo "Test failed" fi # Remove and rescan the NVME device to ensure that it has come back diff --git a/tests/nvme/rc b/tests/nvme/rc index a8f80d8e..68b4beb2 100644 --- a/tests/nvme/rc +++ b/tests/nvme/rc @@ -72,7 +72,7 @@ group_device_requires() { } _require_test_dev_is_nvme_pci() { - if [[ ! "$(readlink -f "$TEST_DEV_SYSFS/device")" =~ devices/pci ]]; then + if [[ ! "$(readlink --canonicalize "$TEST_DEV_SYSFS/device")" =~ devices/pci ]]; then SKIP_REASONS+=("$TEST_DEV is not a PCI NVMe device") return 1 fi @@ -80,13 +80,30 @@ _require_test_dev_is_nvme_pci() { } _require_test_dev_is_not_nvme_multipath() { - if [[ "$(readlink -f "$TEST_DEV_SYSFS/device")" =~ /nvme-subsystem/ ]]; then + if [[ "$(readlink --canonicalize "$TEST_DEV_SYSFS/device")" =~ /nvme-subsystem/ ]]; then SKIP_REASONS+=("$TEST_DEV is a NVMe multipath device") return 1 fi return 0 } +_nvme_dev_support_native_multipath() { + if [[ "$(readlink --canonicalize "$TEST_DEV_SYSFS/device")" =~ /nvme-subsystem/ ]]; then + return 0 + fi + return 1 +} + +_nvme_get_pci_from_dev_sysfs() { + if _nvme_dev_support_native_multipath; then + readlink --canonicalize "$TEST_DEV_SYSFS"/multipath/nvme*c*n*/device | \ + grep -Eo '[0-9a-f]{4,5}:[0-9a-f]{2}:[0-9a-f]{2}\.[0-9a-f]' | \ + tail -1 + else + _get_pci_dev_from_blkdev + fi +} + _require_test_dev_support_sed() { if ! nvme sed discover "$TEST_DEV" &> /dev/null; then SKIP_REASONS+=("$TEST_DEV doesn't support SED operations") @@ -170,12 +187,12 @@ _nvme_get_ctrl_list() { subsys=$(readlink "${TEST_DEV_SYSFS}/device/subsystem") case $subsys in */nvme) - readlink -f "${TEST_DEV_SYSFS}/device" + readlink --canonicalize "${TEST_DEV_SYSFS}/device" ;; */nvme-subsystem) for c in "${TEST_DEV_SYSFS}"/device/nvme*; do [[ -L "$c" ]] || continue - [[ -f "$c/dev" ]] && readlink -f "$c" + [[ -f "$c/dev" ]] && readlink --canonicalize "$c" done ;; esac diff --git a/tests/srp/012 b/tests/srp/012 index 1b343936..478bca4c 100755 --- a/tests/srp/012 +++ b/tests/srp/012 @@ -21,7 +21,7 @@ test_io_schedulers() { fi use_blk_mq ${mq} ${mq} || return $? dev=$(get_bdev 0) || return $? - dm=$(basename "$(readlink -f "${dev}")") || return $? + dm=$(basename "$(readlink --canonicalize "${dev}")") || return $? scheds="$(_io_schedulers "$dm")" || return $? for sched in $scheds; do set_scheduler "$dm" "$sched" \ diff --git a/tests/srp/rc b/tests/srp/rc index 47b95460..e95f925a 100755 --- a/tests/srp/rc +++ b/tests/srp/rc @@ -356,7 +356,7 @@ configure_lio_vdev() { cd "$dirname" && mkdir "$vdev" && cd "$vdev" && - if [ -b "$(readlink -f "$path")" ]; then + if [ -b "$(readlink --canonicalize "$path")" ]; then echo "udev_path=$path," >control elif [ -e "$path" ]; then size=$(stat -c %s "${path}") && @@ -365,7 +365,7 @@ configure_lio_vdev() { else { ls -l "$path" - readlink -f "$path" + readlink --canonicalize "$path" } &>>"$FULL" false fi && @@ -506,7 +506,7 @@ start_lio_srpt() { modprobe ib_srpt "${opts[@]}" || return $? i=0 for r in "${vdev_path[@]}"; do - if [ -b "$(readlink -f "$r")" ]; then + if [ -b "$(readlink --canonicalize "$r")" ]; then oflag=("oflag=direct") else oflag=()