Hi Shinichiro,

Thanks for the test, please see my in-line comments.


On 05/12/2019 07:03 PM, Shin'ichiro Kawasaki wrote:
> Check that zones sector mapping is correct for zoned block devices that
> are not an entire full device (null_block device or physical device).
> These logical devices are for now partition devices or device-mapper
> devices (dm-linear or dm-flakey). This test case requires that such a
> logical device be specified in TEST_DEVS in config. The test is skipped
> for devices that are identified as not logically created.
>
> To test that the zone mapping is correct, select a few sequential write
> required zones of the logical device and move the write pointers of
> these zones through the container device of the logical device, using
> the physical sector mapping of the zones. The write pointers position of
> the selected zones is then checked through a zone report of the logical
> device using the logical sector mapping of the zones. The test reports a
> success if the position of the zone write pointers relative to the zone
> start sector must be identical for both the logical and physical
> locations of the zones.
>
> To implement this test case, introduce several helper functions.
> _find_last_sequential_zone() and _find_sequential_zone_in_middle()
> help target zones selection. _test_dev_is_logical() checks the target
> device type. If false is returned, the test case is skipped.
> _get_dev_container_and_sector() helps to get the container device and
> sector mappings. At this moment, these helper functions support
> partition devices and dm-linear/flakey devices as the logical devices.
> _test_dev_has_dm_map() helps to check that the dm target is linear or
> flakey.
>
> Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
> ---
>   tests/zbd/007     |  95 +++++++++++++++++++++++++++++++++
>   tests/zbd/007.out |   2 +
>   tests/zbd/rc      | 132 ++++++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 229 insertions(+)
>   create mode 100755 tests/zbd/007
>   create mode 100644 tests/zbd/007.out
>
> diff --git a/tests/zbd/007 b/tests/zbd/007
> new file mode 100755
> index 0000000..e4723d7
> --- /dev/null
> +++ b/tests/zbd/007
> @@ -0,0 +1,95 @@
> +#!/bin/bash
> +# SPDX-License-Identifier: GPL-3.0+
> +# Copyright (C) 2019 Western Digital Corporation or its affiliates.
> +#
> +# Test zones are mapped correctly between a logical device and its container
> +# device. Move write pointers of sequential write required zones on the
> +# container devices, and confirm same write pointer positions of zones on the
> +# logical devices.
> +
> +. tests/zbd/rc
> +
> +DESCRIPTION="zone mapping"
Can this be more explanatory ?
> +CAN_BE_ZONED=1
Do we need QUICK=1 ?
> +
> +requires() {
> +     _have_program dmsetup
> +}
> +
> +device_requires() {
> +     _test_dev_is_logical
> +}
> +
> +test_device() {
> +     local -i bs
> +     local -i zone_idx
> +     local -a test_z # test target zones
> +     local -a test_z_start
> +
> +     echo "Running ${TEST_NAME}"
> +
> +     # Get physical block size to meet zoned block device I/O requirement
> +     _get_sysfs_variable "${TEST_DEV}" || return $?
> +     bs=${SYSFS_VARS[SV_PHYS_BLK_SIZE]}
> +     _put_sysfs_variable
> +
> +     # Select test target zones. Pick up the first sequential required zones.
> +     # If available, add one or two more sequential required zones. One is at
> +     # the last end of TEST_DEV. The other is in middle between the first
> +     # and the last zones.
> +     _get_blkzone_report "${TEST_DEV}" || return $?
> +     zone_idx=$(_find_first_sequential_zone) || return $?
> +     test_z=( "${zone_idx}" )
> +     if zone_idx=$(_find_last_sequential_zone); then
> +             test_z+=( "${zone_idx}" )
> +             if zone_idx=$(_find_sequential_zone_in_middle \
> +                                   "${test_z[0]}" "${test_z[1]}"); then
> +                     test_z+=( "${zone_idx}" )
> +             fi
> +     fi
> +
> +     for ((i = 0; i < ${#test_z[@]}; i++)); do
> +             test_z_start+=("${ZONE_STARTS[test_z[i]]}")
> +     done
> +     echo "${test_z[*]}" >> "$FULL"
> +     echo "${test_z_start[*]}" >> "$FULL"
> +
> +     _put_blkzone_report
I think above code of building an array should be move to the same file 
in a helper function. It is just making entire test look bigger than
it is.
> +
> +     # Reset and move write pointers of the container device
> +     for ((i=0; i < ${#test_z[@]}; i++)); do
> +             local -a arr
nit:- add a new line after declaration.
> +             read -r -a arr < <(_get_dev_container_and_sector \
> +                                        "${test_z_start[i]}")
> +             container_dev="${arr[0]}"
> +             container_start="${arr[1]}"
> +
> +             echo "${container_dev}" "${container_start}" >> "$FULL"
> +
> +             blkzone reset -o "${container_start}" -c 1 "${container_dev}"
do we need to check the return value here ?
> +
> +             if ! dd if=/dev/zero of="${container_dev}" bs="${bs}" \
> +                  count=$((4096 * (i + 1) / bs)) oflag=direct \
> +                  seek=$((container_start * 512 / bs)) \
> +                  >> "$FULL" 2>&1 ; then
> +                     echo "dd failed"
> +             fi
> +
> +             # Wait for partition table re-read event settles
> +             udevadm settle
> +     done
> +
> +     # Check write pointer positions on the logical device
> +     _get_blkzone_report "${TEST_DEV}" || return $?
> +     for ((i=0; i < ${#test_z[@]}; i++)); do
> +             if ((ZONE_WPTRS[test_z[i]] != 8 * (i + 1))); then
> +                     echo "Unexpected write pointer position"
> +                     echo -n "zone=${i}, wp=${ZONE_WPTRS[i]}, "
> +                     echo "dev=${TEST_DEV}"
> +             fi
> +             echo "${ZONE_WPTRS[${test_z[i]}]}" >> "$FULL"
> +     done
> +     _put_blkzone_report
> +
> +     echo "Test complete"
> +}
> diff --git a/tests/zbd/007.out b/tests/zbd/007.out
> new file mode 100644
> index 0000000..28a1395
> --- /dev/null
> +++ b/tests/zbd/007.out
> @@ -0,0 +1,2 @@
> +Running zbd/007
> +Test complete
> diff --git a/tests/zbd/rc b/tests/zbd/rc
> index 5f04c84..1168c4e 100644
For rc related code changes can you please send a separate preparation 
patche ? It will be great if we can isolate the actual test from the
rc changes.
> --- a/tests/zbd/rc
> +++ b/tests/zbd/rc
> @@ -193,6 +193,42 @@ _find_first_sequential_zone() {
>       return 1
>   }
>
> +_find_last_sequential_zone() {
> +     for ((idx = REPORTED_COUNT - 1; idx > 0; idx--)); do
> +             if ((ZONE_TYPES[idx] == ZONE_TYPE_SEQ_WRITE_REQUIRED)); then
> +                     echo "${idx}"
> +                     return 0
> +             fi
> +     done
> +
> +     echo "-1"
> +     return 1
> +}
> +
> +# Try to find a sequential required zone between given two zone indices
> +_find_sequential_zone_in_middle() {
> +     local -i s=${1}
> +     local -i e=${2}
> +     local -i idx=$(((s + e) / 2))
> +     local -i i=1
> +
> +     while ((idx != s)) && ((idx != e)); do
> +             if ((ZONE_TYPES[idx] == ZONE_TYPE_SEQ_WRITE_REQUIRED)); then
> +                     echo "${idx}"
> +                     return 0
> +             fi
> +             if ((i%2 == 0)); then
> +                     : $((idx += i))
> +             else
> +                     : $((idx -= i))
> +             fi
> +             : $((i++))
> +     done
> +
> +     echo "-1"
> +     return 1
> +}
> +
>   # Search zones and find two contiguous sequential required zones.
>   # Return index of the first zone of the found two zones.
>   # Call _get_blkzone_report() beforehand.
> @@ -210,3 +246,99 @@ _find_two_contiguous_seq_zones() {
>       echo "Contiguous sequential write required zones not found"
>       return 1
>   }
> +
> +_test_dev_is_dm() {
> +     if [[ ! -r "${TEST_DEV_SYSFS}/dm/name" ]]; then
> +             SKIP_REASON="$TEST_DEV is not device-mapper"
> +             return 1
> +     fi
> +     return 0
> +}
> +
> +_test_dev_is_logical() {
> +     if ! _test_dev_is_partition && ! _test_dev_is_dm; then
> +             SKIP_REASON="$TEST_DEV is not a logical device"
> +             return 1
> +     fi
> +     return 0
> +}
> +
> +_test_dev_has_dm_map() {
> +     local target_type=${1}
> +     local dm_name
nit:- new line after declaration.
> +     dm_name=$(cat "${TEST_DEV_SYSFS}/dm/name")
> +     if ! dmsetup status "${dm_name}" | grep -qe "${target_type}"; then
> +             SKIP_REASON="$TEST_DEV does not have ${target_type} map"
> +             return 1
> +     fi
> +     if dmsetup status "${dm_name}" | grep -v "${target_type}"; then
> +             SKIP_REASON="$TEST_DEV has map other than ${target_type}"
> +             return 1
> +     fi
> +     return 0
> +}
> +
> +# Get device file path from the device ID "major:minor".
> +_get_dev_path_by_id() {
> +     for d in /sys/block/*; do
> +             if [[ ! -r "${d}/dev" ]]; then
> +                     continue
> +             fi
> +             dev_id=$(cat "${d}/dev")
> +             if [[ "${1}" == "${dev_id}" ]]; then
> +                     echo "/dev/${d##*/}"
> +                     return 0
> +             fi
> +     done
> +     return 1
> +}
> +
> +# Given sector of TEST_DEV, return the device which contain the sector and
> +# corresponding sector of the container device.
> +_get_dev_container_and_sector() {
> +     local -i sector=${1}
> +     local cont_dev
> +     local -i offset
> +     local -a tbl_line
> +
> +     if _test_dev_is_partition; then
> +             offset=$(cat "${TEST_DEV_PART_SYSFS}/start")
> +             cont_dev=$(_get_dev_path_by_id "$(cat "${TEST_DEV_SYSFS}/dev")")
> +             echo "${cont_dev}" "$((offset + sector))"
> +             return 0
> +     fi
> +
> +     if ! _test_dev_is_dm; then
> +             echo "${TEST_DEV} is not a logical device"
> +             return 1
> +     fi
> +     if ! _test_dev_has_dm_map linear &&
> +                     ! _test_dev_has_dm_map flakey; then
> +             echo -n "dm mapping test other than linear/flakey is"
> +             echo "not implemented"
> +             return 1
> +     fi
> +
> +     # Parse dm table lines for dm-linear or dm-flakey target
> +     while read -r -a tbl_line; do
> +             local -i map_start=${tbl_line[0]}
> +             local -i map_end=$((tbl_line[0] + tbl_line[1]))
> +             if ((sector < map_start)) || (((map_end) <= sector)); then
> +                     continue
> +             fi
> +
> +             offset=${tbl_line[4]}
> +             if ! cont_dev=$(_get_dev_path_by_id "${tbl_line[3]}"); then
> +                     echo -n "Cannot access to container device: "
> +                     echo "${tbl_line[3]}"
> +                     return 1
> +             fi
> +
> +             echo "${cont_dev}" "$((offset + sector - map_start))"
> +             return 0
> +
> +     done < <(dmsetup table "$(cat "${TEST_DEV_SYSFS}/dm/name")")
> +
> +     echo -n "Cannot find container device of ${TEST_DEV}"
> +     return 1
> +}
>

Reply via email to