* [PATCH v3 blktests 0/2] Add atomic write tests for scsi and nvme @ 2025-02-05 23:10 Alan Adamson 2025-02-05 23:10 ` [PATCH v3 blktests 1/2] scsi/009: add atomic write tests Alan Adamson 2025-02-05 23:11 ` [PATCH v3 blktests 2/2] nvme/059: " Alan Adamson 0 siblings, 2 replies; 7+ messages in thread From: Alan Adamson @ 2025-02-05 23:10 UTC (permalink / raw) To: linux-block; +Cc: linux-scsi, alan.adamson, linux-nvme, shinichiro.kawasaki Changes in v3: - Remove _have_xfs_io routine and use _have_program. - Comment cleanup in 0001 - Add SKIP_REASONS when xfs_io -A option is absent. - Keep lines <=80 characters. - Move device_requires logic in 0001 and 0002 to common/rc. Changes in v2: - Add additional comments in common/xfs - Remove xfs_io and kernel version checking - Simplify paths for sysfs attributes - Fix failed case output (missing echo) in scsi/009 - Add local variable that sets Test # and description (test_desc) for scsi/009 and nvme/059 - Only use scsi_debug device if no scsi test device is provided. - nvme testing done with qemu-nvme. - scsi testing done with scsi_debug and qemu-scsi (no atomic write support). No testing on atomic write capable scsi devices was done. ------------------------------------------------------------------------------------------- Add tests for atomic write support. Tests will be delivered for scsi (using scsi_debug) and nvme. NVMe can use the qemu-nvme emulated device that supports Controller-based Atomic Parameters (QEMU 9.2). The xfs_io utility delivered with the xfsprogs-devel package (version 6.12) is required by these tests. The Linux Kernel 6.11 (and greater) supports Atomic Writes and is required by these tests. Alan Adamson (2): scsi/009: add atomic write tests nvme/059: add atomic write tests common/rc | 8 ++ common/xfs | 58 ++++++++++++ tests/nvme/059 | 147 +++++++++++++++++++++++++++++ tests/nvme/059.out | 10 ++ tests/scsi/009 | 229 +++++++++++++++++++++++++++++++++++++++++++++ tests/scsi/009.out | 18 ++++ 6 files changed, 470 insertions(+) create mode 100755 tests/nvme/059 create mode 100644 tests/nvme/059.out create mode 100755 tests/scsi/009 create mode 100644 tests/scsi/009.out -- 2.43.5 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 blktests 1/2] scsi/009: add atomic write tests 2025-02-05 23:10 [PATCH v3 blktests 0/2] Add atomic write tests for scsi and nvme Alan Adamson @ 2025-02-05 23:10 ` Alan Adamson 2025-02-06 6:00 ` Chaitanya Kulkarni 2025-02-06 11:57 ` John Garry 2025-02-05 23:11 ` [PATCH v3 blktests 2/2] nvme/059: " Alan Adamson 1 sibling, 2 replies; 7+ messages in thread From: Alan Adamson @ 2025-02-05 23:10 UTC (permalink / raw) To: linux-block; +Cc: linux-scsi, alan.adamson, linux-nvme, shinichiro.kawasaki Tests basic atomic write functionality. If no scsi test device is provided, a scsi_debug device will be used. Testing areas include: - Verify sysfs atomic write attributes are consistent with atomic write attributes advertised by scsi_debug. - Verify the atomic write paramters of statx are correct using xfs_io. - Perform a pwritev2() (with and without RWF_ATOMIC flag) using xfs_io: - maximum byte size (atomic_write_unit_max_bytes) - minimum byte size (atomic_write_unit_min_bytes) - a write larger than atomic_write_unit_max_bytes - a write smaller than atomic_write_unit_min_bytes Signed-off-by: Alan Adamson <alan.adamson@oracle.com> --- common/rc | 8 ++ common/xfs | 58 ++++++++++++ tests/scsi/009 | 229 +++++++++++++++++++++++++++++++++++++++++++++ tests/scsi/009.out | 18 ++++ 4 files changed, 313 insertions(+) create mode 100755 tests/scsi/009 create mode 100644 tests/scsi/009.out diff --git a/common/rc b/common/rc index bcb215d35114..06c0a416e3e1 100644 --- a/common/rc +++ b/common/rc @@ -292,6 +292,14 @@ _require_test_dev_can_discard() { return 0 } +_require_device_support_atomic_writes() { + _require_test_dev_sysfs queue/atomic_write_max_bytes + if (( $(< "${TEST_DEV_SYSFS}"/queue/atomic_write_max_bytes) == 0 )); then + SKIP_REASONS+=("${TEST_DEV} does not support atomic write") + return 1 + fi +} + _test_dev_queue_get() { if [[ $1 = scheduler ]]; then sed -e 's/.*\[//' -e 's/\].*//' "${TEST_DEV_SYSFS}/queue/scheduler" diff --git a/common/xfs b/common/xfs index 569770fecd53..0b1ca7c29049 100644 --- a/common/xfs +++ b/common/xfs @@ -6,6 +6,22 @@ . common/shellcheck +_have_xfs_io_atomic_write() { + local s + + _have_program xfs_io || return $? + + # If the pwrite command supports the -A option then this version + # of xfs_io supports atomic writes. + s=$(xfs_io -c help | grep pwrite | awk '{ print $4}') + if [[ $s == *"A"* ]]; + then + return 0 + fi + SKIP_REASONS+=("xfs_io does not support the -A option") + return 1 +} + _have_xfs() { _have_fs xfs && _have_program mkfs.xfs } @@ -52,3 +68,45 @@ _xfs_run_fio_verify_io() { return "${rc}" } + +# Use xfs_io to perform a non-atomic write using pwritev2(). +# Args: $1 - device to write to +# $2 - number of bytes to write +# Returns: Number of bytes written +run_xfs_io_pwritev2() { + local dev=$1 + local bytes_to_write=$2 + local bytes_written + + # Perform write and extract out bytes written from xfs_io output + bytes_written=$(xfs_io -d -C \ + "pwrite -b ${bytes_to_write} -V 1 -D 0 ${bytes_to_write}" \ + "$dev" | grep "wrote" | sed 's/\// /g' | awk '{ print $2 }') + echo "$bytes_written" +} + +# Use xfs_io to perform an atomic write using pwritev2(). +# Args: $1 - device to write to +# $2 - number of bytes to write +# Returns: Number of bytes written +run_xfs_io_pwritev2_atomic() { + local dev=$1 + local bytes_to_write=$2 + local bytes_written + + # Perform atomic write and extract out bytes written from xfs_io output + bytes_written=$(xfs_io -d -C \ + "pwrite -b ${bytes_to_write} -V 1 -A -D 0 ${bytes_to_write}" \ + "$dev" | grep "wrote" | sed 's/\// /g' | awk '{ print $2 }') + echo "$bytes_written" +} + +run_xfs_io_xstat() { + local dev=$1 + local field=$2 + local statx_output + + statx_output=$(xfs_io -c "statx -r -m 0x00010000" "$dev" | \ + grep "$field" | awk '{ print $3 }') + echo "$statx_output" +} diff --git a/tests/scsi/009 b/tests/scsi/009 new file mode 100755 index 000000000000..b114d92dd3db --- /dev/null +++ b/tests/scsi/009 @@ -0,0 +1,229 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-3.0+ +# Copyright (C) 2025 Oracle and/or its affiliates +# +# Test SCSI Atomic Writes with scsi_debug + +. tests/scsi/rc +. common/scsi_debug +. common/xfs + +DESCRIPTION="test scsi atomic writes" +QUICK=1 + +requires() { + _have_driver scsi_debug + _have_xfs_io_atomic_write +} + +device_requires() { + _require_device_support_atomic_writes +} + +fallback_device() { + local scsi_debug_params=( + delay=0 + atomic_wr=1 + ) + if ! _configure_scsi_debug "${scsi_debug_params[@]}"; then + return 1 + fi + echo "/dev/${SCSI_DEBUG_DEVICES[0]}" +} + +cleanup_fallback_device() { + _exit_scsi_debug +} + +test_device() { + local scsi_debug_atomic_wr_max_length + local scsi_debug_atomic_wr_gran + local scsi_atomic_max_bytes + local scsi_atomic_min_bytes + local sysfs_max_hw_sectors_kb + local max_hw_bytes + local sysfs_logical_block_size + local sysfs_atomic_max_bytes + local sysfs_atomic_unit_max_bytes + local sysfs_atomic_unit_min_bytes + local statx_atomic_min + local statx_atomic_max + local bytes_to_write + local bytes_written + local test_desc + + echo "Running ${TEST_NAME}" + + sysfs_logical_block_size=$(< "${TEST_DEV_SYSFS}"/queue/logical_block_size) + sysfs_max_hw_sectors_kb=$(< "${TEST_DEV_SYSFS}"/queue/max_hw_sectors_kb) + max_hw_bytes=$(( "$sysfs_max_hw_sectors_kb" * 1024 )) + sysfs_atomic_max_bytes=$(< "${TEST_DEV_SYSFS}"/queue/atomic_write_max_bytes) + sysfs_atomic_unit_max_bytes=$(< "${TEST_DEV_SYSFS}"/queue/atomic_write_unit_max_bytes) + sysfs_atomic_unit_min_bytes=$(< "${TEST_DEV_SYSFS}"/queue/atomic_write_unit_min_bytes) + scsi_debug_atomic_wr_max_length=$(< /sys/module/scsi_debug/parameters/atomic_wr_max_length) + scsi_debug_atomic_wr_gran=$(< /sys/module/scsi_debug/parameters/atomic_wr_gran) + scsi_atomic_max_bytes=$(( "$scsi_debug_atomic_wr_max_length" * "$sysfs_logical_block_size" )) + scsi_atomic_min_bytes=$(( "$scsi_debug_atomic_wr_gran" * "$sysfs_logical_block_size" )) + + test_desc="TEST 1 - Verify sysfs atomic attributes" + if [ "$max_hw_bytes" -ge "$sysfs_atomic_max_bytes" ] && + [ "$sysfs_atomic_max_bytes" -ge "$sysfs_atomic_unit_max_bytes" ] && + [ "$sysfs_atomic_unit_max_bytes" -ge "$sysfs_atomic_unit_min_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $max_hw_bytes - $sysfs_max_hw_sectors_kb -" \ + "$sysfs_atomic_max_bytes - $sysfs_atomic_unit_max_bytes -" \ + "$sysfs_atomic_unit_min_bytes" + fi + + test_desc="TEST 2 - check scsi_debug atomic_wr_max_length is the same as sysfs atomic_write_max_bytes" + if [ "$scsi_atomic_max_bytes" -le "$max_hw_bytes" ] + then + if [ "$scsi_atomic_max_bytes" = "$sysfs_atomic_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $scsi_atomic_max_bytes - $max_hw_bytes -" \ + "$sysfs_atomic_max_bytes" + fi + else + if [ "$sysfs_atomic_max_bytes" = "$max_hw_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $scsi_atomic_max_bytes - $max_hw_bytes -" \ + "$sysfs_atomic_max_bytes" + fi + fi + + test_desc="TEST 3 - check sysfs atomic_write_unit_max_bytes <= scsi_debug atomic_wr_max_length" + if (("$sysfs_atomic_unit_max_bytes" <= "$scsi_atomic_max_bytes")) + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $sysfs_atomic_unit_max_bytes - $scsi_atomic_max_bytes" + fi + + test_desc="TEST 4 - check sysfs atomic_write_unit_min_bytes = scsi_debug atomic_wr_gran" + if [ "$sysfs_atomic_unit_min_bytes" = "$scsi_atomic_min_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $sysfs_atomic_unit_min_bytes - $scsi_atomic_min_bytes" + fi + + test_desc="TEST 5 - check statx stx_atomic_write_unit_min" + statx_atomic_min=$(run_xfs_io_xstat "$TEST_DEV" "stat.atomic_write_unit_min") + if [ "$statx_atomic_min" = "$scsi_atomic_min_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $statx_atomic_min - $scsi_atomic_min_bytes" + fi + + test_desc="TEST 6 - check statx stx_atomic_write_unit_max" + statx_atomic_max=$(run_xfs_io_xstat "$TEST_DEV" "stat.atomic_write_unit_max") + if [ "$statx_atomic_max" = "$sysfs_atomic_unit_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $statx_atomic_max - $sysfs_atomic_unit_max_bytes" + fi + + test_desc="TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes " + test_desc+="with no RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$sysfs_atomic_unit_max_bytes") + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" + fi + + test_desc="TEST 8 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with " + test_desc+="RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$sysfs_atomic_unit_max_bytes") + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" + fi + + test_desc="TEST 9 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 " + test_desc+="bytes with no RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_to_write=$(( "${sysfs_atomic_unit_max_bytes}" + "$sysfs_logical_block_size" )) + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$bytes_to_write") + if [ "$bytes_written" = "$bytes_to_write" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $bytes_to_write" + fi + + test_desc="TEST 10 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 " + test_desc+="bytes with RWF_ATOMIC flag - pwritev2 should not be succesful" + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$bytes_to_write") + if [ "$bytes_written" = "" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $bytes_to_write" + fi + + test_desc="TEST 11 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes " + test_desc+="with no RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$sysfs_atomic_unit_min_bytes") + if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $scsi_atomic_min_bytes" + fi + + test_desc="TEST 12 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes " + test_desc+="with RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$sysfs_atomic_unit_min_bytes") + if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $scsi_atomic_min_bytes" + fi + + test_desc="TEST 13 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 " + test_desc+="bytes with no RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_to_write=$(( "${sysfs_atomic_unit_min_bytes}" - "${sysfs_logical_block_size}" )) + if [ "$bytes_to_write" = 0 ] + then + echo "$test_desc - pass" + echo "pwrite: Invalid argument" + else + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$bytes_to_write") + if [ "$bytes_written" = "$bytes_to_write" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $bytes_to_write" + fi + fi + test_desc="TEST 14 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 " + test_desc+="bytes with RWF_ATOMIC flag - pwritev2 should fail" + if [ "$bytes_to_write" = 0 ] + then + echo "$test_desc - pass" + else + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$bytes_to_write") + if [ "$bytes_written" = "" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $bytes_to_write" + fi + fi + + _exit_scsi_debug + + echo "Test complete" +} diff --git a/tests/scsi/009.out b/tests/scsi/009.out new file mode 100644 index 000000000000..e31416b93515 --- /dev/null +++ b/tests/scsi/009.out @@ -0,0 +1,18 @@ +Running scsi/009 +TEST 1 - Verify sysfs atomic attributes - pass +TEST 2 - check scsi_debug atomic_wr_max_length is the same as sysfs atomic_write_max_bytes - pass +TEST 3 - check sysfs atomic_write_unit_max_bytes <= scsi_debug atomic_wr_max_length - pass +TEST 4 - check sysfs atomic_write_unit_min_bytes = scsi_debug atomic_wr_gran - pass +TEST 5 - check statx stx_atomic_write_unit_min - pass +TEST 6 - check statx stx_atomic_write_unit_max - pass +TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass +TEST 8 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should be succesful - pass +TEST 9 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass +pwrite: Invalid argument +TEST 10 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 bytes with RWF_ATOMIC flag - pwritev2 should not be succesful - pass +TEST 11 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass +TEST 12 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with RWF_ATOMIC flag - pwritev2 should be succesful - pass +TEST 13 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass +pwrite: Invalid argument +TEST 14 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 bytes with RWF_ATOMIC flag - pwritev2 should fail - pass +Test complete -- 2.43.5 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 blktests 1/2] scsi/009: add atomic write tests 2025-02-05 23:10 ` [PATCH v3 blktests 1/2] scsi/009: add atomic write tests Alan Adamson @ 2025-02-06 6:00 ` Chaitanya Kulkarni 2025-02-06 11:57 ` John Garry 1 sibling, 0 replies; 7+ messages in thread From: Chaitanya Kulkarni @ 2025-02-06 6:00 UTC (permalink / raw) To: Alan Adamson, linux-block@vger.kernel.org Cc: linux-scsi@vger.kernel.org, linux-nvme@lists.infradead.org, shinichiro.kawasaki@wdc.com On 2/5/25 15:10, Alan Adamson wrote: > Tests basic atomic write functionality. If no scsi test device is provided, > a scsi_debug device will be used. Testing areas include: > > - Verify sysfs atomic write attributes are consistent with > atomic write attributes advertised by scsi_debug. > - Verify the atomic write paramters of statx are correct using > xfs_io. > - Perform a pwritev2() (with and without RWF_ATOMIC flag) using > xfs_io: > - maximum byte size (atomic_write_unit_max_bytes) > - minimum byte size (atomic_write_unit_min_bytes) > - a write larger than atomic_write_unit_max_bytes > - a write smaller than atomic_write_unit_min_bytes > > Signed-off-by: Alan Adamson<alan.adamson@oracle.com> Looks good. Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> -ck ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 blktests 1/2] scsi/009: add atomic write tests 2025-02-05 23:10 ` [PATCH v3 blktests 1/2] scsi/009: add atomic write tests Alan Adamson 2025-02-06 6:00 ` Chaitanya Kulkarni @ 2025-02-06 11:57 ` John Garry 1 sibling, 0 replies; 7+ messages in thread From: John Garry @ 2025-02-06 11:57 UTC (permalink / raw) To: Alan Adamson, linux-block; +Cc: linux-scsi, linux-nvme, shinichiro.kawasaki On 05/02/2025 23:10, Alan Adamson wrote: > Tests basic atomic write functionality. If no scsi test device is provided, > a scsi_debug device will be used. Testing areas include: > > - Verify sysfs atomic write attributes are consistent with > atomic write attributes advertised by scsi_debug. > - Verify the atomic write paramters of statx are correct using > xfs_io. > - Perform a pwritev2() (with and without RWF_ATOMIC flag) using > xfs_io: > - maximum byte size (atomic_write_unit_max_bytes) > - minimum byte size (atomic_write_unit_min_bytes) > - a write larger than atomic_write_unit_max_bytes > - a write smaller than atomic_write_unit_min_bytes > > Signed-off-by: Alan Adamson <alan.adamson@oracle.com> generally looks ok, thanks, but a couple of comments > --- > common/rc | 8 ++ > common/xfs | 58 ++++++++++++ I suppose that this common stuff could go in a separate prep patch, but it doesn't bother me too much > tests/scsi/009 | 229 +++++++++++++++++++++++++++++++++++++++++++++ > tests/scsi/009.out | 18 ++++ > 4 files changed, 313 insertions(+) > create mode 100755 tests/scsi/009 > create mode 100644 tests/scsi/009.out > > diff --git a/common/rc b/common/rc > index bcb215d35114..06c0a416e3e1 100644 > --- a/common/rc > +++ b/common/rc > @@ -292,6 +292,14 @@ _require_test_dev_can_discard() { > return 0 > } > > +_require_device_support_atomic_writes() { > + _require_test_dev_sysfs queue/atomic_write_max_bytes > + if (( $(< "${TEST_DEV_SYSFS}"/queue/atomic_write_max_bytes) == 0 )); then > + SKIP_REASONS+=("${TEST_DEV} does not support atomic write") > + return 1 > + fi > +} > + > _test_dev_queue_get() { > if [[ $1 = scheduler ]]; then > sed -e 's/.*\[//' -e 's/\].*//' "${TEST_DEV_SYSFS}/queue/scheduler" > diff --git a/common/xfs b/common/xfs > index 569770fecd53..0b1ca7c29049 100644 > --- a/common/xfs > +++ b/common/xfs > @@ -6,6 +6,22 @@ > > . common/shellcheck > > +_have_xfs_io_atomic_write() { > + local s > + > + _have_program xfs_io || return $? > + > + # If the pwrite command supports the -A option then this version > + # of xfs_io supports atomic writes. > + s=$(xfs_io -c help | grep pwrite | awk '{ print $4}') > + if [[ $s == *"A"* ]]; > + then > + return 0 > + fi > + SKIP_REASONS+=("xfs_io does not support the -A option") > + return 1 > +} > + > _have_xfs() { > _have_fs xfs && _have_program mkfs.xfs > } > @@ -52,3 +68,45 @@ _xfs_run_fio_verify_io() { > > return "${rc}" > } > + > +# Use xfs_io to perform a non-atomic write using pwritev2(). > +# Args: $1 - device to write to > +# $2 - number of bytes to write > +# Returns: Number of bytes written > +run_xfs_io_pwritev2() { > + local dev=$1 > + local bytes_to_write=$2 > + local bytes_written > + > + # Perform write and extract out bytes written from xfs_io output > + bytes_written=$(xfs_io -d -C \ > + "pwrite -b ${bytes_to_write} -V 1 -D 0 ${bytes_to_write}" \ > + "$dev" | grep "wrote" | sed 's/\// /g' | awk '{ print $2 }') > + echo "$bytes_written" > +} > + > +# Use xfs_io to perform an atomic write using pwritev2(). > +# Args: $1 - device to write to > +# $2 - number of bytes to write > +# Returns: Number of bytes written > +run_xfs_io_pwritev2_atomic() { > + local dev=$1 > + local bytes_to_write=$2 > + local bytes_written > + > + # Perform atomic write and extract out bytes written from xfs_io output > + bytes_written=$(xfs_io -d -C \ > + "pwrite -b ${bytes_to_write} -V 1 -A -D 0 ${bytes_to_write}" \ > + "$dev" | grep "wrote" | sed 's/\// /g' | awk '{ print $2 }') > + echo "$bytes_written" > +} > + > +run_xfs_io_xstat() { > + local dev=$1 > + local field=$2 > + local statx_output > + > + statx_output=$(xfs_io -c "statx -r -m 0x00010000" "$dev" | \ > + grep "$field" | awk '{ print $3 }') > + echo "$statx_output" > +} > diff --git a/tests/scsi/009 b/tests/scsi/009 > new file mode 100755 > index 000000000000..b114d92dd3db > --- /dev/null > +++ b/tests/scsi/009 > @@ -0,0 +1,229 @@ > +#!/bin/bash > +# SPDX-License-Identifier: GPL-3.0+ > +# Copyright (C) 2025 Oracle and/or its affiliates > +# > +# Test SCSI Atomic Writes with scsi_debug > + > +. tests/scsi/rc > +. common/scsi_debug > +. common/xfs > + > +DESCRIPTION="test scsi atomic writes" > +QUICK=1 > + > +requires() { > + _have_driver scsi_debug > + _have_xfs_io_atomic_write > +} > + > +device_requires() { > + _require_device_support_atomic_writes > +} > + > +fallback_device() { > + local scsi_debug_params=( > + delay=0 > + atomic_wr=1 > + ) > + if ! _configure_scsi_debug "${scsi_debug_params[@]}"; then > + return 1 > + fi > + echo "/dev/${SCSI_DEBUG_DEVICES[0]}" > +} > + > +cleanup_fallback_device() { > + _exit_scsi_debug > +} > + > +test_device() { > + local scsi_debug_atomic_wr_max_length > + local scsi_debug_atomic_wr_gran > + local scsi_atomic_max_bytes > + local scsi_atomic_min_bytes > + local sysfs_max_hw_sectors_kb > + local max_hw_bytes > + local sysfs_logical_block_size > + local sysfs_atomic_max_bytes > + local sysfs_atomic_unit_max_bytes > + local sysfs_atomic_unit_min_bytes > + local statx_atomic_min > + local statx_atomic_max > + local bytes_to_write > + local bytes_written > + local test_desc > + > + echo "Running ${TEST_NAME}" > + > + sysfs_logical_block_size=$(< "${TEST_DEV_SYSFS}"/queue/logical_block_size) > + sysfs_max_hw_sectors_kb=$(< "${TEST_DEV_SYSFS}"/queue/max_hw_sectors_kb) > + max_hw_bytes=$(( "$sysfs_max_hw_sectors_kb" * 1024 )) > + sysfs_atomic_max_bytes=$(< "${TEST_DEV_SYSFS}"/queue/atomic_write_max_bytes) > + sysfs_atomic_unit_max_bytes=$(< "${TEST_DEV_SYSFS}"/queue/atomic_write_unit_max_bytes) > + sysfs_atomic_unit_min_bytes=$(< "${TEST_DEV_SYSFS}"/queue/atomic_write_unit_min_bytes) > + scsi_debug_atomic_wr_max_length=$(< /sys/module/scsi_debug/parameters/atomic_wr_max_length) > + scsi_debug_atomic_wr_gran=$(< /sys/module/scsi_debug/parameters/atomic_wr_gran) > + scsi_atomic_max_bytes=$(( "$scsi_debug_atomic_wr_max_length" * "$sysfs_logical_block_size" )) > + scsi_atomic_min_bytes=$(( "$scsi_debug_atomic_wr_gran" * "$sysfs_logical_block_size" )) > + > + test_desc="TEST 1 - Verify sysfs atomic attributes" > + if [ "$max_hw_bytes" -ge "$sysfs_atomic_max_bytes" ] && > + [ "$sysfs_atomic_max_bytes" -ge "$sysfs_atomic_unit_max_bytes" ] && > + [ "$sysfs_atomic_unit_max_bytes" -ge "$sysfs_atomic_unit_min_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $max_hw_bytes - $sysfs_max_hw_sectors_kb -" \ > + "$sysfs_atomic_max_bytes - $sysfs_atomic_unit_max_bytes -" \ > + "$sysfs_atomic_unit_min_bytes" > + fi > + > + test_desc="TEST 2 - check scsi_debug atomic_wr_max_length is the same as sysfs atomic_write_max_bytes" > + if [ "$scsi_atomic_max_bytes" -le "$max_hw_bytes" ] > + then > + if [ "$scsi_atomic_max_bytes" = "$sysfs_atomic_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $scsi_atomic_max_bytes - $max_hw_bytes -" \ > + "$sysfs_atomic_max_bytes" > + fi > + else > + if [ "$sysfs_atomic_max_bytes" = "$max_hw_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $scsi_atomic_max_bytes - $max_hw_bytes -" \ > + "$sysfs_atomic_max_bytes" > + fi > + fi > + > + test_desc="TEST 3 - check sysfs atomic_write_unit_max_bytes <= scsi_debug atomic_wr_max_length" > + if (("$sysfs_atomic_unit_max_bytes" <= "$scsi_atomic_max_bytes")) > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $sysfs_atomic_unit_max_bytes - $scsi_atomic_max_bytes" > + fi > + > + test_desc="TEST 4 - check sysfs atomic_write_unit_min_bytes = scsi_debug atomic_wr_gran" > + if [ "$sysfs_atomic_unit_min_bytes" = "$scsi_atomic_min_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $sysfs_atomic_unit_min_bytes - $scsi_atomic_min_bytes" > + fi > + > + test_desc="TEST 5 - check statx stx_atomic_write_unit_min" > + statx_atomic_min=$(run_xfs_io_xstat "$TEST_DEV" "stat.atomic_write_unit_min") > + if [ "$statx_atomic_min" = "$scsi_atomic_min_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $statx_atomic_min - $scsi_atomic_min_bytes" > + fi > + > + test_desc="TEST 6 - check statx stx_atomic_write_unit_max" > + statx_atomic_max=$(run_xfs_io_xstat "$TEST_DEV" "stat.atomic_write_unit_max") > + if [ "$statx_atomic_max" = "$sysfs_atomic_unit_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $statx_atomic_max - $sysfs_atomic_unit_max_bytes" > + fi > + > + test_desc="TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes " > + test_desc+="with no RWF_ATOMIC flag - pwritev2 should be succesful" > + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$sysfs_atomic_unit_max_bytes") > + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" > + fi > + > + test_desc="TEST 8 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with " > + test_desc+="RWF_ATOMIC flag - pwritev2 should be succesful" > + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$sysfs_atomic_unit_max_bytes") > + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" > + fi > + > + test_desc="TEST 9 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 " > + test_desc+="bytes with no RWF_ATOMIC flag - pwritev2 should be succesful" > + bytes_to_write=$(( "${sysfs_atomic_unit_max_bytes}" + "$sysfs_logical_block_size" )) > + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$bytes_to_write") > + if [ "$bytes_written" = "$bytes_to_write" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $bytes_to_write" > + fi > + > + test_desc="TEST 10 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 " > + test_desc+="bytes with RWF_ATOMIC flag - pwritev2 should not be succesful" > + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$bytes_to_write") > + if [ "$bytes_written" = "" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $bytes_to_write" > + fi > + > + test_desc="TEST 11 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes " > + test_desc+="with no RWF_ATOMIC flag - pwritev2 should be succesful" > + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$sysfs_atomic_unit_min_bytes") > + if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $scsi_atomic_min_bytes" > + fi > + > + test_desc="TEST 12 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes " > + test_desc+="with RWF_ATOMIC flag - pwritev2 should be succesful" > + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$sysfs_atomic_unit_min_bytes") > + if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $scsi_atomic_min_bytes" > + fi > + > + test_desc="TEST 13 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 " > + test_desc+="bytes with no RWF_ATOMIC flag - pwritev2 should be succesful" Again, I am not really sure that testing with RWF_ATOMIC has any value here. > + bytes_to_write=$(( "${sysfs_atomic_unit_min_bytes}" - "${sysfs_logical_block_size}" )) > + if [ "$bytes_to_write" = 0 ] > + then > + echo "$test_desc - pass" > + echo "pwrite: Invalid argument" > + else > + bytes_written=$(run_xfs_io_pwritev2 "$TEST_DEV" "$bytes_to_write") > + if [ "$bytes_written" = "$bytes_to_write" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $bytes_to_write" > + fi > + fi > + test_desc="TEST 14 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 " > + test_desc+="bytes with RWF_ATOMIC flag - pwritev2 should fail" > + if [ "$bytes_to_write" = 0 ] > + then > + echo "$test_desc - pass" > + else > + bytes_written=$(run_xfs_io_pwritev2_atomic "$TEST_DEV" "$bytes_to_write") > + if [ "$bytes_written" = "" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $bytes_to_write" > + fi > + fi > + > + _exit_scsi_debug > + > + echo "Test complete" > +} > diff --git a/tests/scsi/009.out b/tests/scsi/009.out > new file mode 100644 > index 000000000000..e31416b93515 > --- /dev/null > +++ b/tests/scsi/009.out > @@ -0,0 +1,18 @@ > +Running scsi/009 > +TEST 1 - Verify sysfs atomic attributes - pass > +TEST 2 - check scsi_debug atomic_wr_max_length is the same as sysfs atomic_write_max_bytes - pass > +TEST 3 - check sysfs atomic_write_unit_max_bytes <= scsi_debug atomic_wr_max_length - pass > +TEST 4 - check sysfs atomic_write_unit_min_bytes = scsi_debug atomic_wr_gran - pass > +TEST 5 - check statx stx_atomic_write_unit_min - pass > +TEST 6 - check statx stx_atomic_write_unit_max - pass > +TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass > +TEST 8 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should be succesful - pass > +TEST 9 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass > +pwrite: Invalid argument > +TEST 10 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 bytes with RWF_ATOMIC flag - pwritev2 should not be succesful - pass > +TEST 11 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass > +TEST 12 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with RWF_ATOMIC flag - pwritev2 should be succesful - pass > +TEST 13 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 bytes with no RWF_ATOMIC flag - pwritev2 should be succesful - pass > +pwrite: Invalid argument > +TEST 14 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 bytes with RWF_ATOMIC flag - pwritev2 should fail - pass > +Test complete ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 blktests 2/2] nvme/059: add atomic write tests 2025-02-05 23:10 [PATCH v3 blktests 0/2] Add atomic write tests for scsi and nvme Alan Adamson 2025-02-05 23:10 ` [PATCH v3 blktests 1/2] scsi/009: add atomic write tests Alan Adamson @ 2025-02-05 23:11 ` Alan Adamson 2025-02-06 6:01 ` Chaitanya Kulkarni 2025-02-06 11:47 ` John Garry 1 sibling, 2 replies; 7+ messages in thread From: Alan Adamson @ 2025-02-05 23:11 UTC (permalink / raw) To: linux-block; +Cc: linux-scsi, alan.adamson, linux-nvme, shinichiro.kawasaki Tests basic atomic write functionality using NVMe devices that support the AWUN and AWUPF Controller Atomic Parameters and NAWUN and NAWUPF Namespace Atomic Parameters. Testing areas include: - Verify sysfs atomic write attributes are consistent with atomic write capablities advertised by the NVMe HW. - Verify the atomic write paramters of statx are correct using xfs_io. - Perform a pwritev2() (with and without RWF_ATOMIC flag) using xfs_io: - maximum byte size (atomic_write_unit_max_bytes) - a write larger than atomic_write_unit_max_bytes Signed-off-by: Alan Adamson <alan.adamson@oracle.com> --- tests/nvme/059 | 147 +++++++++++++++++++++++++++++++++++++++++++++ tests/nvme/059.out | 10 +++ 2 files changed, 157 insertions(+) create mode 100755 tests/nvme/059 create mode 100644 tests/nvme/059.out diff --git a/tests/nvme/059 b/tests/nvme/059 new file mode 100755 index 000000000000..24b2bec645a8 --- /dev/null +++ b/tests/nvme/059 @@ -0,0 +1,147 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-3.0+ +# Copyright (C) 2025 Oracle and/or its affiliates +# +# Test NVMe Atomic Writes + +. tests/nvme/rc +. common/xfs + +DESCRIPTION="test atomic writes" +QUICK=1 + +requires() { + _nvme_requires + _have_program nvme + _have_xfs_io_atomic_write +} + +device_requires() { + _require_device_support_atomic_writes +} + +test_device() { + local ns_dev + local ctrl_dev + local queue_path + local nvme_awupf + local nvme_nsfeat + local nvme_nsabp + local atomic_max_bytes + local statx_atomic_max + local sysfs_atomic_max_bytes + local sysfs_atomic_unit_max_bytes + local sysfs_logical_block_size + local bytes_written + local bytes_to_write + local test_desc + + echo "Running ${TEST_NAME}" + ns_dev=${TEST_DEV##*/} + ctrl_dev=${ns_dev%n*} + queue_path="${TEST_DEV_SYSFS}/queue/" + + test_desc="TEST 1 - Verify sysfs attributes" + + sysfs_logical_block_size=$(cat "$queue_path"/logical_block_size) + sysfs_max_hw_sectors_kb=$(cat "$queue_path"/max_hw_sectors_kb) + max_hw_bytes=$(( "$sysfs_max_hw_sectors_kb" * 1024 )) + sysfs_atomic_max_bytes=$(cat "$queue_path"/atomic_write_max_bytes) + sysfs_atomic_unit_max_bytes=$(cat "$queue_path"/atomic_write_unit_max_bytes) + sysfs_atomic_unit_min_bytes=$(cat "$queue_path"/atomic_write_unit_min_bytes) + + if [ "$max_hw_bytes" -ge "$sysfs_atomic_max_bytes" ] && + [ "$sysfs_atomic_max_bytes" -ge "$sysfs_atomic_unit_max_bytes" ] && + [ "$sysfs_atomic_unit_max_bytes" -ge "$sysfs_atomic_unit_min_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $max_hw_bytes - $sysfs_max_hw_sectors_kb -" \ + "$sysfs_atomic_max_bytes - $sysfs_atomic_unit_max_bytes -" \ + "$sysfs_atomic_unit_min_bytes" + fi + + test_desc="TEST 2 - Verify sysfs atomic_write_unit_max_bytes is consistent " + test_desc+="with NVMe AWUPF/NAWUPF" + nvme_nsfeat=$(nvme id-ns /dev/"${ns_dev}" | grep nsfeat | awk '{ print $3}') + nvme_nsabp=$((("$nvme_nsfeat" & 0x2) != 0)) + if [ "$nvme_nsabp" = 1 ] # Check if NSABP is set + then + nvme_awupf=$(nvme id-ns /dev/"$ns_dev" | grep nawupf | awk '{ print $3}') + atomic_max_bytes=$(( ("$nvme_awupf" + 1) * "$sysfs_logical_block_size" )) + else + nvme_awupf=$(nvme id-ctrl /dev/"${ctrl_dev}" | grep awupf | awk '{ print $3}') + atomic_max_bytes=$(( ("$nvme_awupf" + 1) * "$sysfs_logical_block_size" )) + fi + if [ "$atomic_max_bytes" -le "$max_hw_bytes" ] + then + if [ "$atomic_max_bytes" = "$sysfs_atomic_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $nvme_nsabp - $atomic_max_bytes - $sysfs_atomic_max_bytes -" \ + "$max_hw_bytes" + fi + else + if [ "$sysfs_atomic_max_bytes" = "$max_hw_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $nvme_nsabp - $atomic_max_bytes - $sysfs_atomic_max_bytes -" \ + "$max_hw_bytes" + fi + fi + + test_desc="TEST 3 - Verify statx is correctly reporting atomic_unit_max_bytes" + statx_atomic_max=$(run_xfs_io_xstat /dev/"$ns_dev" "stat.atomic_write_unit_max") + if [ "$sysfs_atomic_unit_max_bytes" = "$statx_atomic_max" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $statx_atomic_max - $sysfs_atomic_unit_max_bytes" + fi + + test_desc="TEST 4 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes "\ + test_desc+="with no RWF_ATOMIC" + # flag - pwritev2 should be succesful. + bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns_dev" "$sysfs_atomic_unit_max_bytes") + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" + fi + + test_desc="TEST 5 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with " + test_desc+="RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_written=$(run_xfs_io_pwritev2_atomic /dev/"$ns_dev" "$sysfs_atomic_unit_max_bytes") + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" + fi + + test_desc="TEST 6 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 1 logical " + test_desc+="block with no RWF_ATOMIC flag - pwritev2 should be succesful" + bytes_to_write=$(( "$sysfs_atomic_unit_max_bytes" + "$sysfs_logical_block_size" )) + bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns_dev" "$bytes_to_write") + if [ "$bytes_written" = "$bytes_to_write" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $bytes_to_write" + fi + + test_desc="TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + logical " + test_desc+="block with RWF_ATOMIC flag - pwritev2 should not be succesful" + bytes_written=$(run_xfs_io_pwritev2_atomic /dev/"$ns_dev" "$bytes_to_write") + if [ "$bytes_written" = "" ] + then + echo "$test_desc - pass" + else + echo "$test_desc - fail $bytes_written - $bytes_to_write" + fi + + echo "Test complete" +} diff --git a/tests/nvme/059.out b/tests/nvme/059.out new file mode 100644 index 000000000000..e803de35776f --- /dev/null +++ b/tests/nvme/059.out @@ -0,0 +1,10 @@ +Running nvme/059 +TEST 1 - Verify sysfs attributes - pass +TEST 2 - Verify sysfs atomic_write_unit_max_bytes is consistent with NVMe AWUPF/NAWUPF - pass +TEST 3 - Verify statx is correctly reporting atomic_unit_max_bytes - pass +TEST 4 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with no RWF_ATOMIC - pass +TEST 5 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should be succesful - pass +TEST 6 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 1 logical block with no RWF_ATOMIC flag - pwritev2 should be succesful - pass +pwrite: Invalid argument +TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + logical block with RWF_ATOMIC flag - pwritev2 should not be succesful - pass +Test complete -- 2.43.5 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v3 blktests 2/2] nvme/059: add atomic write tests 2025-02-05 23:11 ` [PATCH v3 blktests 2/2] nvme/059: " Alan Adamson @ 2025-02-06 6:01 ` Chaitanya Kulkarni 2025-02-06 11:47 ` John Garry 1 sibling, 0 replies; 7+ messages in thread From: Chaitanya Kulkarni @ 2025-02-06 6:01 UTC (permalink / raw) To: Alan Adamson, linux-block@vger.kernel.org Cc: linux-scsi@vger.kernel.org, linux-nvme@lists.infradead.org, shinichiro.kawasaki@wdc.com On 2/5/25 15:11, Alan Adamson wrote: > Tests basic atomic write functionality using NVMe devices > that support the AWUN and AWUPF Controller Atomic Parameters > and NAWUN and NAWUPF Namespace Atomic Parameters. > > Testing areas include: > > - Verify sysfs atomic write attributes are consistent with > atomic write capablities advertised by the NVMe HW. > > - Verify the atomic write paramters of statx are correct using > xfs_io. > > - Perform a pwritev2() (with and without RWF_ATOMIC flag) using > xfs_io: > - maximum byte size (atomic_write_unit_max_bytes) > - a write larger than atomic_write_unit_max_bytes > > Signed-off-by: Alan Adamson<alan.adamson@oracle.com> Looks good. Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com> -ck ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 blktests 2/2] nvme/059: add atomic write tests 2025-02-05 23:11 ` [PATCH v3 blktests 2/2] nvme/059: " Alan Adamson 2025-02-06 6:01 ` Chaitanya Kulkarni @ 2025-02-06 11:47 ` John Garry 1 sibling, 0 replies; 7+ messages in thread From: John Garry @ 2025-02-06 11:47 UTC (permalink / raw) To: Alan Adamson, linux-block; +Cc: linux-scsi, linux-nvme, shinichiro.kawasaki On 05/02/2025 23:11, Alan Adamson wrote: > Tests basic atomic write functionality using NVMe devices > that support the AWUN and AWUPF Controller Atomic Parameters > and NAWUN and NAWUPF Namespace Atomic Parameters. > > Testing areas include: > > - Verify sysfs atomic write attributes are consistent with > atomic write capablities advertised by the NVMe HW. > > - Verify the atomic write paramters of statx are correct using > xfs_io. > > - Perform a pwritev2() (with and without RWF_ATOMIC flag) using > xfs_io: > - maximum byte size (atomic_write_unit_max_bytes) > - a write larger than atomic_write_unit_max_bytes > > Signed-off-by: Alan Adamson <alan.adamson@oracle.com> Generally this looks ok, but some comments below. > --- > tests/nvme/059 | 147 +++++++++++++++++++++++++++++++++++++++++++++ > tests/nvme/059.out | 10 +++ > 2 files changed, 157 insertions(+) > create mode 100755 tests/nvme/059 > create mode 100644 tests/nvme/059.out > > diff --git a/tests/nvme/059 b/tests/nvme/059 > new file mode 100755 > index 000000000000..24b2bec645a8 > --- /dev/null > +++ b/tests/nvme/059 > @@ -0,0 +1,147 @@ > +#!/bin/bash > +# SPDX-License-Identifier: GPL-3.0+ > +# Copyright (C) 2025 Oracle and/or its affiliates > +# > +# Test NVMe Atomic Writes > + > +. tests/nvme/rc > +. common/xfs > + > +DESCRIPTION="test atomic writes" > +QUICK=1 > + > +requires() { > + _nvme_requires > + _have_program nvme > + _have_xfs_io_atomic_write > +} > + > +device_requires() { > + _require_device_support_atomic_writes > +} > + > +test_device() { > + local ns_dev > + local ctrl_dev > + local queue_path > + local nvme_awupf > + local nvme_nsfeat > + local nvme_nsabp > + local atomic_max_bytes > + local statx_atomic_max > + local sysfs_atomic_max_bytes > + local sysfs_atomic_unit_max_bytes > + local sysfs_logical_block_size > + local bytes_written > + local bytes_to_write > + local test_desc > + > + echo "Running ${TEST_NAME}" > + ns_dev=${TEST_DEV##*/} > + ctrl_dev=${ns_dev%n*} > + queue_path="${TEST_DEV_SYSFS}/queue/" > + > + test_desc="TEST 1 - Verify sysfs attributes" > + > + sysfs_logical_block_size=$(cat "$queue_path"/logical_block_size) > + sysfs_max_hw_sectors_kb=$(cat "$queue_path"/max_hw_sectors_kb) > + max_hw_bytes=$(( "$sysfs_max_hw_sectors_kb" * 1024 )) > + sysfs_atomic_max_bytes=$(cat "$queue_path"/atomic_write_max_bytes) > + sysfs_atomic_unit_max_bytes=$(cat "$queue_path"/atomic_write_unit_max_bytes) > + sysfs_atomic_unit_min_bytes=$(cat "$queue_path"/atomic_write_unit_min_bytes) > + > + if [ "$max_hw_bytes" -ge "$sysfs_atomic_max_bytes" ] && > + [ "$sysfs_atomic_max_bytes" -ge "$sysfs_atomic_unit_max_bytes" ] && > + [ "$sysfs_atomic_unit_max_bytes" -ge "$sysfs_atomic_unit_min_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $max_hw_bytes - $sysfs_max_hw_sectors_kb -" \ > + "$sysfs_atomic_max_bytes - $sysfs_atomic_unit_max_bytes -" \ > + "$sysfs_atomic_unit_min_bytes" > + fi > + > + test_desc="TEST 2 - Verify sysfs atomic_write_unit_max_bytes is consistent " > + test_desc+="with NVMe AWUPF/NAWUPF" > + nvme_nsfeat=$(nvme id-ns /dev/"${ns_dev}" | grep nsfeat | awk '{ print $3}') > + nvme_nsabp=$((("$nvme_nsfeat" & 0x2) != 0)) > + if [ "$nvme_nsabp" = 1 ] # Check if NSABP is set > + then > + nvme_awupf=$(nvme id-ns /dev/"$ns_dev" | grep nawupf | awk '{ print $3}') > + atomic_max_bytes=$(( ("$nvme_awupf" + 1) * "$sysfs_logical_block_size" )) > + else > + nvme_awupf=$(nvme id-ctrl /dev/"${ctrl_dev}" | grep awupf | awk '{ print $3}') > + atomic_max_bytes=$(( ("$nvme_awupf" + 1) * "$sysfs_logical_block_size" )) > + fi > + if [ "$atomic_max_bytes" -le "$max_hw_bytes" ] > + then > + if [ "$atomic_max_bytes" = "$sysfs_atomic_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $nvme_nsabp - $atomic_max_bytes - $sysfs_atomic_max_bytes -" \ > + "$max_hw_bytes" > + fi > + else > + if [ "$sysfs_atomic_max_bytes" = "$max_hw_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $nvme_nsabp - $atomic_max_bytes - $sysfs_atomic_max_bytes -" \ > + "$max_hw_bytes" > + fi > + fi > + > + test_desc="TEST 3 - Verify statx is correctly reporting atomic_unit_max_bytes" I suppose that you can also check atomic_unit_min_bytes And min can be checked in other tests (when applicable). > + statx_atomic_max=$(run_xfs_io_xstat /dev/"$ns_dev" "stat.atomic_write_unit_max") > + if [ "$sysfs_atomic_unit_max_bytes" = "$statx_atomic_max" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $statx_atomic_max - $sysfs_atomic_unit_max_bytes" > + fi > + > + test_desc="TEST 4 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes "\ > + test_desc+="with no RWF_ATOMIC" > + # flag - pwritev2 should be succesful. > + bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns_dev" "$sysfs_atomic_unit_max_bytes") > + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" > + fi > + > + test_desc="TEST 5 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with " > + test_desc+="RWF_ATOMIC flag - pwritev2 should be succesful" > + bytes_written=$(run_xfs_io_pwritev2_atomic /dev/"$ns_dev" "$sysfs_atomic_unit_max_bytes") > + if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $sysfs_atomic_unit_max_bytes" > + fi > + > + test_desc="TEST 6 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 1 logical " > + test_desc+="block with no RWF_ATOMIC flag - pwritev2 should be succesful" I don't really see much value in this test. If this doesn't pass, then something is really wrong. > + bytes_to_write=$(( "$sysfs_atomic_unit_max_bytes" + "$sysfs_logical_block_size" )) > + bytes_written=$(run_xfs_io_pwritev2 /dev/"$ns_dev" "$bytes_to_write") > + if [ "$bytes_written" = "$bytes_to_write" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $bytes_to_write" > + fi > + > + test_desc="TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + logical " > + test_desc+="block with RWF_ATOMIC flag - pwritev2 should not be succesful" nit: I really don't think that "succesful" is the proper spelling > + bytes_written=$(run_xfs_io_pwritev2_atomic /dev/"$ns_dev" "$bytes_to_write") > + if [ "$bytes_written" = "" ] > + then > + echo "$test_desc - pass" > + else > + echo "$test_desc - fail $bytes_written - $bytes_to_write" > + fi > + > + echo "Test complete" > +} > diff --git a/tests/nvme/059.out b/tests/nvme/059.out > new file mode 100644 > index 000000000000..e803de35776f > --- /dev/null > +++ b/tests/nvme/059.out > @@ -0,0 +1,10 @@ > +Running nvme/059 > +TEST 1 - Verify sysfs attributes - pass > +TEST 2 - Verify sysfs atomic_write_unit_max_bytes is consistent with NVMe AWUPF/NAWUPF - pass > +TEST 3 - Verify statx is correctly reporting atomic_unit_max_bytes - pass > +TEST 4 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with no RWF_ATOMIC - pass > +TEST 5 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should be succesful - pass > +TEST 6 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 1 logical block with no RWF_ATOMIC flag - pwritev2 should be succesful - pass > +pwrite: Invalid argument > +TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + logical block with RWF_ATOMIC flag - pwritev2 should not be succesful - pass > +Test complete ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-02-06 11:57 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-02-05 23:10 [PATCH v3 blktests 0/2] Add atomic write tests for scsi and nvme Alan Adamson 2025-02-05 23:10 ` [PATCH v3 blktests 1/2] scsi/009: add atomic write tests Alan Adamson 2025-02-06 6:00 ` Chaitanya Kulkarni 2025-02-06 11:57 ` John Garry 2025-02-05 23:11 ` [PATCH v3 blktests 2/2] nvme/059: " Alan Adamson 2025-02-06 6:01 ` Chaitanya Kulkarni 2025-02-06 11:47 ` John Garry
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox