From patchwork Wed Jan 9 01:35:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Damien Le Moal X-Patchwork-Id: 10753335 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C7A4A91E for ; Wed, 9 Jan 2019 01:36:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B4D4E28C8B for ; Wed, 9 Jan 2019 01:36:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A969628DD7; Wed, 9 Jan 2019 01:36:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 046AC28C8B for ; Wed, 9 Jan 2019 01:36:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729445AbfAIBga (ORCPT ); Tue, 8 Jan 2019 20:36:30 -0500 Received: from esa1.hgst.iphmx.com ([68.232.141.245]:65001 "EHLO esa1.hgst.iphmx.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728854AbfAIBga (ORCPT ); Tue, 8 Jan 2019 20:36:30 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1546997790; x=1578533790; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=lyt7r4Nk6Sj/E5Qs3yz610FPVB+RX3EmSmmLTyVYEw4=; b=Mo7kycFktuhTMZKShrlvXafl6euCr42JlQQxJe7D2wLltStyE/2MBCsS zcX4Wl8he5QcYg+EQwtgNT3hWwhbJD1kTYj1RV9yII+KG23BGNWZzioGD J8v7fCFCAAKSZKuAKfmJ0yCsA9yvOtlpszOMQMR/xzn8X1SgQrP88mlNl Wf7VvTLulaKlG73ek9q9UTMy7w0Ixe0YhOEZvj9W5nNkFciPXItQnuf05 M12K6ICQaPhOtGhf3vd/1XdwCnEIpU22o8j+AZOKIkGslA3yRvYE+VbIx OI/jDHN06Pab9GIY3ai15iAehtSn/Pm6EQVZSjXPj9levfRD8j8rbU72G Q==; X-IronPort-AV: E=Sophos;i="5.56,455,1539619200"; d="scan'208";a="203169207" Received: from uls-op-cesaip01.wdc.com (HELO uls-op-cesaep01.wdc.com) ([199.255.45.14]) by ob1.hgst.iphmx.com with ESMTP; 09 Jan 2019 09:36:29 +0800 Received: from uls-op-cesaip01.wdc.com ([10.248.3.36]) by uls-op-cesaep01.wdc.com with ESMTP; 08 Jan 2019 17:16:30 -0800 Received: from washi.fujisawa.hgst.com ([10.149.53.254]) by uls-op-cesaip01.wdc.com with ESMTP; 08 Jan 2019 17:36:27 -0800 From: Damien Le Moal To: linux-block@vger.kernel.org, Omar Sandoval , Masato Suzuki , Shinichiro Kawasaki Cc: Omar Sandoval , Jens Axboe , Matias Bjorling , Hannes Reinecke , Mike Snitzer , "Martin K . Petersen" Subject: [PATCH blktests 09/14] tests: Introduce zbd test group Date: Wed, 9 Jan 2019 10:35:37 +0900 Message-Id: <20190109013542.23686-10-damien.lemoal@wdc.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190109013542.23686-1-damien.lemoal@wdc.com> References: <20190109013542.23686-1-damien.lemoal@wdc.com> MIME-Version: 1.0 Sender: linux-block-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-block@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Masato Suzuki The zoned block device (zbd) test group is used to gather all tests specific to zoned block devices (null_blk device with zoned mode enabled, SMR disks, dm-linear on top of zoned devices, etc). Execution of this group requires that the kernel be compiled with the block layer CONFIG_BLK_DEV_ZONED option enabled and also requires the null_blk driver to have zoned mode support (added in kernel 4.19). This group rc script allows all tests to operate even if TEST_DEVS is not set in the config. If TEST_DEVS is not set, the rc script creates a null_blk device with zoned mode enabled and the created device assigned to TEST_DEVS. If TEST_DEVS is set, all tests are executed against the specified devices, which all must be zoned. With this, all tests scripts can be written by only defining the test_device() function while allowing operation on both nullblk and user specified devices. Signed-off-by: Shin'ichiro Kawasaki Signed-off-by: Masato Suzuki --- tests/zbd/rc | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 tests/zbd/rc diff --git a/tests/zbd/rc b/tests/zbd/rc new file mode 100644 index 0000000..bf68264 --- /dev/null +++ b/tests/zbd/rc @@ -0,0 +1,250 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-3.0+ +# Copyright (C) 2018 Western Digital Corporation or its affiliates. +# +# Tests for Zone Block Device. + +. common/rc +. common/null_blk + +# +# Test requirement check functions +# + +group_requires() { + _have_root || return $? + _have_program blkzone || return $? + _have_program dd || return $? + _have_kernel_option BLK_DEV_ZONED || return $? + _have_modules null_blk && _have_module_param null_blk zoned + + # If TEST_DEVS is set in config file, use it as is. + # Otherwise, create a zoned null_blk device and set TEST_DEVS. + if [[ -n "${TEST_DEVS}" ]] ; then + return 0 + fi + + local test_dev + local sysfs_dir + if ! _init_null_blk zone_size=4 gb=1 zoned=1 ; then + return 1 + fi + test_dev=/dev/nullb0 + if ! sysfs_dir="$(_find_sysfs_dir "$test_dev")"; then + _error "could not find sysfs directory for ${test_dev}" + return 1 + fi + export _NULL_BLK_ZONED_CREATED=1 + TEST_DEVS+=( "${test_dev}" ) + + # shellcheck disable=SC2034 + TEST_DEV_SYSFS_DIRS["$test_dev"]="$sysfs_dir" + + return 0 +} + +group_device_requires() { + _test_dev_is_zoned +} + +group_exit() { + if [[ -n "${_NULL_BLK_ZONED_CREATED}" ]] ; then + _exit_null_blk + unset _NULL_BLK_ZONED_CREATED + fi +} + +# +# Zone types and conditions +# +export ZONE_TYPE_CONVENTIONAL=1 +export ZONE_TYPE_SEQ_WRITE_REQUIRED=2 +export ZONE_TYPE_SEQ_WRITE_PREFERRED=3 + +export ZONE_COND_EMPTY=1 +export ZONE_COND_IMPLICIT_OPEN=2 +export ZONE_COND_FULL=14 + +export ZONE_TYPE_ARRAY=( + [1]="CONVENTIONAL" + [2]="SEQ_WRITE_REQUIRED" + [3]="SEQ_WRITE_PREFERRED" +) + +export ZONE_COND_ARRAY=( + [0]="NOT_WP" + [1]="EMPTY" + [2]="IMPLICIT_OPEN" + [3]="EXPLICIT_OPEN" + [4]="CLOSE" + [13]="READ_ONLY" + [14]="FULL" + [15]="OFFLINE" +) + +# sysfs variable array indices +export SV_CAPACITY=0 +export SV_CHUNK_SECTORS=1 +export SV_PHYS_BLK_SIZE=2 +export SV_PHYS_BLK_SECTORS=3 +export SV_NR_ZONES=4 + +# +# Helper functions +# + +# Obtain zone related sysfs variables and keep in a global array until put +# function call. +_get_sysfs_variable() { + unset SYSFS_VARS + local _dir=${TEST_DEV_SYSFS} + SYSFS_VARS[$SV_CAPACITY]=$(<"${_dir}"/size) + SYSFS_VARS[$SV_CHUNK_SECTORS]=$(<"${_dir}"/queue/chunk_sectors) + SYSFS_VARS[$SV_PHYS_BLK_SIZE]=$(<"${_dir}"/queue/physical_block_size) + SYSFS_VARS[$SV_PHYS_BLK_SECTORS]=$((SYSFS_VARS[SV_PHYS_BLK_SIZE] / 512)) + + # If the nr_zones sysfs attribute exists, get its value. Otherwise, + # calculate its value based on the total capacity and zone size, taking + # into account that the last zone can be smaller than other zones. + if [[ -e ${TEST_DEV_SYSFS}/queue/nr_zones ]]; then + SYSFS_VARS[$SV_NR_ZONES]=$(<"${_dir}"/queue/nr_zones) + else + SYSFS_VARS[$SV_NR_ZONES]=$(( (SYSFS_VARS[SV_CAPACITY] - 1) \ + / SYSFS_VARS[SV_CHUNK_SECTORS] + 1 )) + fi +} + +_put_sysfs_variable() { + unset SYSFS_VARS +} + +# Issue zone report command and keep reported information in global arrays +# until put function call. +_get_blkzone_report() { + local target_dev=${1} + + # Initialize arrays to store parsed blkzone reports. + # Number of reported zones is set in REPORTED_COUNT. + # The arrays have REPORTED_COUNT+1 elements with additional one at tail + # to simplify loop operation. + ZONE_STARTS=() + ZONE_LENGTHS=() + ZONE_WPTRS=() + ZONE_CONDS=() + ZONE_TYPES=() + NR_CONV_ZONES=0 + REPORTED_COUNT=0 + + TMP_REPORT_FILE=${TMPDIR}/blkzone_report + if ! blkzone report "${target_dev}" > "${TMP_REPORT_FILE}"; then + echo "blkzone command failed" + return $? + fi + + local _IFS=$IFS + local -i loop=0 + IFS=$' ,:' + while read -r -a _tokens + do + ZONE_STARTS+=($((_tokens[1]))) + ZONE_LENGTHS+=($((_tokens[3]))) + ZONE_WPTRS+=($((_tokens[5]))) + ZONE_CONDS+=($((${_tokens[11]%\(*}))) + ZONE_TYPES+=($((${_tokens[13]%\(*}))) + if [[ ${ZONE_TYPES[-1]} -eq ${ZONE_TYPE_CONVENTIONAL} ]]; then + (( NR_CONV_ZONES++ )) + fi + (( loop++ )) + done < "${TMP_REPORT_FILE}" + IFS="$_IFS" + REPORTED_COUNT=${loop} + + if [[ ${REPORTED_COUNT} -eq 0 ]] ; then + echo "blkzone report returned no zone" + return 1 + fi + + # Set value to allow additioanl element access at array end + local -i max_idx=$((REPORTED_COUNT - 1)) + ZONE_STARTS+=( $((ZONE_STARTS[max_idx] + ZONE_LENGTHS[max_idx])) ) + ZONE_LENGTHS+=( "${ZONE_LENGTHS[max_idx]}" ) + ZONE_WPTRS+=( "${ZONE_WPTRS[max_idx]}" ) + ZONE_CONDS+=( "${ZONE_CONDS[max_idx]}" ) + ZONE_TYPES+=( "${ZONE_TYPES[max_idx]}" ) + + rm -f "${TMP_REPORT_FILE}" +} + +_put_blkzone_report() { + unset ZONE_STARTS + unset ZONE_LENGTHS + unset ZONE_WPTRS + unset ZONE_CONDS + unset ZONE_TYPES + unset REPORTED_COUNT + unset NR_CONV_ZONES +} + +# Issue reset zone command with zone count option. +# Call _get_blkzone_report() beforehand. +_reset_zones() { + local target_dev=${1} + local -i idx=${2} + local -i count=${3} + + if ! blkzone reset -o "${ZONE_STARTS[idx]}" -c "${count}" \ + "${target_dev}" >> "$FULL" 2>&1 ; then + echo "blkzone reset command failed" + return 1 + fi +} + +# Issue dd command with five arguments and record command line in FULL file. +# args: target device, r/w, start sector, sector len, block size in bytes +_dd() { + local target_dev=${1} + local rw=${2} + local -i start_sector=${3} + local -i start_byte=$(( start_sector * 512 )) + local -i sector_count=${4} + local -i bs=${5} + local -i block_count=$(( sector_count * 512 / bs )) + + local _cmd="dd bs=${bs} count=${block_count}" + + if [[ ${rw} = "read" ]]; then + _cmd="${_cmd} if=${target_dev} of=/dev/null" + _cmd="${_cmd} iflag=skip_bytes skip=${start_byte}" + elif [[ ${rw} = "write" ]]; then + _cmd="${_cmd} if=/dev/zero of=${target_dev}" + _cmd="${_cmd} oflag=seek_bytes,direct seek=${start_byte}" + fi + + echo "${_cmd}" >> "$FULL" 2>&1 + + if ! eval "${_cmd}" >> "$FULL" 2>&1 ; then + echo "dd command failed" + return 1 + fi + + sync +} + +# 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. +_find_two_contiguous_seq_zones() { + local -i type_seq=${ZONE_TYPE_SEQ_WRITE_REQUIRED} + for ((idx = NR_CONV_ZONES; idx < REPORTED_COUNT; idx++)); do + if [[ ${ZONE_TYPES[idx]} -eq ${type_seq} && + ${ZONE_TYPES[idx+1]} -eq ${type_seq} ]]; + then + echo "${idx}" + return 0 + fi + done + + echo "Contiguous sequential write required zones not found" + return 1 +} +