diff mbox series

[blktests,1/2] scsi/009: add atomic write tests

Message ID 20250121222530.2824516-2-alan.adamson@oracle.com
State New
Headers show
Series Add atomic write tests for scsi and nvme | expand

Commit Message

Alan Adamson Jan. 21, 2025, 10:25 p.m. UTC
Uses scsi_debug to test basic atomic write functionality. 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/xfs         |  49 +++++++++++
 tests/scsi/009     | 213 +++++++++++++++++++++++++++++++++++++++++++++
 tests/scsi/009.out |  18 ++++
 3 files changed, 280 insertions(+)
 create mode 100755 tests/scsi/009
 create mode 100644 tests/scsi/009.out

Comments

Chaitanya Kulkarni Jan. 22, 2025, 12:51 a.m. UTC | #1
On 1/21/25 14:25, Alan Adamson wrote:
> Uses scsi_debug to test basic atomic write functionality. 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>

Thanks a lot for the testcase, this is really useful based on
amount of work has been done on the kernel side.

> ---
>   common/xfs         |  49 +++++++++++
>   tests/scsi/009     | 213 +++++++++++++++++++++++++++++++++++++++++++++
>   tests/scsi/009.out |  18 ++++
>   3 files changed, 280 insertions(+)
>   create mode 100755 tests/scsi/009
>   create mode 100644 tests/scsi/009.out
>
> diff --git a/common/xfs b/common/xfs
> index 569770fecd53..284c6d7cdc40 100644
> --- a/common/xfs
> +++ b/common/xfs
> @@ -6,6 +6,28 @@
>   
>   . common/shellcheck
>   
> +_have_xfs_io() {
> +	if ! _have_program xfs_io; then
> +		return 1
> +	fi
> +	return 0
> +}
> +
> +# Check whether the version of xfs_io is greater than or equal to $1.$2.$3
> +_have_xfs_io_ver() {
> +	local d=$1 e=$2 f=$3
> +
> +	_have_xfs_io || return $?
> +
> +	IFS='.' read -r a b c < <(xfs_io -V | sed 's/xfs_io version *//')
> +	if [ $((a * 65536 + b * 256 + c)) -lt $((d * 65536 + e * 256 + f)) ];

can we add some comments for above calculations ?

> +	then
> +		SKIP_REASONS+=("xfs_io version too old")
> +		return 1
> +	fi
> +	return 0
> +}
> +
>   _have_xfs() {
>   	_have_fs xfs && _have_program mkfs.xfs
>   }
> @@ -52,3 +74,30 @@ _xfs_run_fio_verify_io() {
>   
>   	return "${rc}"
>   }
> +
> +run_xfs_io_pwritev2() {
> +	local dev=$1
> +	local bytes_to_write=$2
> +	local bytes_written
> +
> +	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 }')

same here little comment would be really useful

> +	echo "$bytes_written"
> +}
> +
> +run_xfs_io_pwritev2_atomic() {
> +	local dev=$1
> +	local bytes_to_write=$2
> +	local bytes_written
> +
> +	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 }')

same here

> +	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 }')

same here

> +	echo "$statx_output"
> +}
> diff --git a/tests/scsi/009 b/tests/scsi/009
> new file mode 100755
> index 000000000000..f3ab00f61369
> --- /dev/null
> +++ b/tests/scsi/009
> @@ -0,0 +1,213 @@
> +#!/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_kver 6 11
> +	_have_xfs_io_ver 6 12 0
> +}
> +
> +test() {
> +	local dev
> +	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
> +
> +	echo "Running ${TEST_NAME}"
> +
> +	local scsi_debug_params=(
> +		delay=0
> +		atomic_wr=1
> +	)
> +	_configure_scsi_debug "${scsi_debug_params[@]}"
> +	dev="/dev/${SCSI_DEBUG_DEVICES[0]}"
> +	sysfs_logical_block_size=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/logical_block_size)

you can also use the local variable for following path to trim down the
cat operations where :-

/sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue

makes the code easy to read ...

> +	sysfs_max_hw_sectors_kb=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/max_hw_sectors_kb)
> +	max_hw_bytes=$(( "$sysfs_max_hw_sectors_kb" * 1024 ))
> +	sysfs_atomic_max_bytes=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/atomic_write_max_bytes)
> +	sysfs_atomic_unit_max_bytes=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/atomic_write_unit_max_bytes)
> +	sysfs_atomic_unit_min_bytes=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/atomic_write_unit_min_bytes)
> +	scsi_debug_atomic_wr_max_length=$(cat /sys/module/scsi_debug/parameters/atomic_wr_max_length)
> +	scsi_debug_atomic_wr_gran=$(cat /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 1 - Verify sysfs atomic attributes

I'd use local test_desc var and assign the above description
string in the above comment and use that in the echo

> +	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 1 - pass"
> +	else
> +		"TEST 1 - fail $max_hw_bytes - $sysfs_max_hw_sectors_kb -" \
> +			"$sysfs_atomic_max_bytes - $sysfs_atomic_unit_max_bytes -" \
> +			"$sysfs_atomic_unit_min_bytes"

I think echo is missing above ?

> +	fi
> +
> +	# 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 2 - pass"
> +		else
> +			echo "TEST 2 - 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 2 - pass"
> +		else
> +			echo "TEST 2 - fail $scsi_atomic_max_bytes - $max_hw_bytes -" \
> +				"$sysfs_atomic_max_bytes"
> +		fi
> +	fi
> +

same comment here for 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 3 - pass"
> +	else
> +		echo "TEST 3 - fail $sysfs_atomic_unit_max_bytes - $scsi_atomic_max_bytes"
> +	fi
> +

same comment here for 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 4 - pass"
> +	else
> +		echo "TEST 4 - fail $sysfs_atomic_unit_min_bytes - $scsi_atomic_min_bytes"
> +	fi
> +

same comment here for test_desc

> +	# TEST 5 - check statx stx_atomic_write_unit_min
> +	statx_atomic_min=$(run_xfs_io_xstat "$dev" "stat.atomic_write_unit_min")
> +	if [ "$statx_atomic_min" = "$scsi_atomic_min_bytes" ]
> +	then
> +		echo "TEST 5 - pass"
> +	else
> +		echo "TEST 5 - fail $statx_atomic_min - $scsi_atomic_min_bytes"
> +	fi
> +

same comment here for test_desc

> +	# TEST  6 - check statx stx_atomic_write_unit_max
> +	statx_atomic_max=$(run_xfs_io_xstat "$dev" "stat.atomic_write_unit_max")
> +	if [ "$statx_atomic_max" = "$sysfs_atomic_unit_max_bytes" ]
> +	then
> +		echo "TEST 6 - pass"
> +	else
> +		echo "TEST 6 - fail $statx_atomic_max - $sysfs_atomic_unit_max_bytes"
> +	fi
> +

same comment here for test_desc

> +	# TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with no RWF_ATOMIC flag - pwritev2 should
> +	# be succesful.
> +	bytes_written=$(run_xfs_io_pwritev2 "$dev" "$sysfs_atomic_unit_max_bytes")
> +	if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ]
> +	then
> +		echo "TEST 7 - pass"
> +	else
> +		echo "TEST 7 - fail $bytes_written - $sysfs_atomic_unit_max_bytes"
> +	fi
> +
> +	# TEST 8 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should
> +	# be succesful.
> +	bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$sysfs_atomic_unit_max_bytes")
> +	if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ]
> +	then
> +		echo "TEST 8 - pass"
> +	else
> +		echo "TEST 8 - fail $bytes_written - $sysfs_atomic_unit_max_bytes"
> +	fi
> +

same comment here for test_desc

> +	# TEST 9 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 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 "$dev" "$bytes_to_write")
> +	if [ "$bytes_written" = "$bytes_to_write" ]
> +	then
> +		echo "TEST 9 - pass"
> +	else
> +		echo "TEST 9 - fail $bytes_written - $bytes_to_write"
> +	fi
> +

same comment here for test_desc

> +	# TEST 10 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 bytes with RWF_ATOMIC flag - pwritev2
> +	# should not be succesful.
> +	bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$bytes_to_write")
> +	if [ "$bytes_written" = "" ]
> +	then
> +		echo "TEST 10 - pass"
> +	else
> +		echo "TEST 10 - fail $bytes_written - $bytes_to_write"
> +	fi
> +

same comment here for test_desc

> +	# TEST 11 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with no RWF_ATOMIC flag - pwritev2 should
> +	# be succesful.
> +	bytes_written=$(run_xfs_io_pwritev2 "$dev" "$sysfs_atomic_unit_min_bytes")
> +	if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ]
> +	then
> +		echo "TEST 11 - pass"
> +	else
> +		echo "TEST 11 - fail $bytes_written - $scsi_atomic_min_bytes"
> +	fi
> +

same comment here for test_desc

> +	# TEST 12 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with RWF_ATOMIC flag - pwritev2 should
> +	# be succesful.
> +	bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$sysfs_atomic_unit_min_bytes")
> +	if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ]
> +	then
> +		echo "TEST 12 - pass"
> +	else
> +		echo "TEST 12 - fail $bytes_written - $scsi_atomic_min_bytes"
> +	fi

same comment here for test_desc

> +	# 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.
> +	# TEST 14 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 bytes with
> +        # RWF_ATOMIC flag - pwritev2 should fail.
> +	bytes_to_write=$(( "${sysfs_atomic_unit_min_bytes}" - "${sysfs_logical_block_size}" ))
> +	if [ "$bytes_to_write" = 0 ]
> +	then
> +		# sysfs_atomic_unit_min_bytes is set to 1 logical block so these tests aren't needed.
> +		echo "TEST 13 - pass"
> +		echo "TEST 14 - pass"
> +	else
> +		bytes_written=$(run_xfs_io_pwritev2 "$dev" "$bytes_to_write")
> +		if [ "$bytes_written" = "$bytes_to_write" ]
> +		then
> +			echo "TEST 13 - pass"
> +		else
> +			echo "TEST 13 - fail $bytes_written - $bytes_to_write"
> +		fi
> +		bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$bytes_to_write")
> +		if [ "$bytes_written" = "" ]
> +		then
> +			echo "TEST 14 - pass"
> +		else
> +			echo "TEST 14 - fail $bytes_written - $bytes_to_write"
> +		fi
> +	fi
> +

same comment here for test_desc


-ck
diff mbox series

Patch

diff --git a/common/xfs b/common/xfs
index 569770fecd53..284c6d7cdc40 100644
--- a/common/xfs
+++ b/common/xfs
@@ -6,6 +6,28 @@ 
 
 . common/shellcheck
 
+_have_xfs_io() {
+	if ! _have_program xfs_io; then
+		return 1
+	fi
+	return 0
+}
+
+# Check whether the version of xfs_io is greater than or equal to $1.$2.$3
+_have_xfs_io_ver() {
+	local d=$1 e=$2 f=$3
+
+	_have_xfs_io || return $?
+
+	IFS='.' read -r a b c < <(xfs_io -V | sed 's/xfs_io version *//')
+	if [ $((a * 65536 + b * 256 + c)) -lt $((d * 65536 + e * 256 + f)) ];
+	then
+		SKIP_REASONS+=("xfs_io version too old")
+		return 1
+	fi
+	return 0
+}
+
 _have_xfs() {
 	_have_fs xfs && _have_program mkfs.xfs
 }
@@ -52,3 +74,30 @@  _xfs_run_fio_verify_io() {
 
 	return "${rc}"
 }
+
+run_xfs_io_pwritev2() {
+	local dev=$1
+	local bytes_to_write=$2
+	local bytes_written
+
+	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"
+}
+
+run_xfs_io_pwritev2_atomic() {
+	local dev=$1
+	local bytes_to_write=$2
+	local bytes_written
+
+	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..f3ab00f61369
--- /dev/null
+++ b/tests/scsi/009
@@ -0,0 +1,213 @@ 
+#!/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_kver 6 11
+	_have_xfs_io_ver 6 12 0
+}
+
+test() {
+	local dev
+	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
+
+	echo "Running ${TEST_NAME}"
+
+	local scsi_debug_params=(
+		delay=0
+		atomic_wr=1
+	)
+	_configure_scsi_debug "${scsi_debug_params[@]}"
+	dev="/dev/${SCSI_DEBUG_DEVICES[0]}"
+	sysfs_logical_block_size=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/logical_block_size)
+	sysfs_max_hw_sectors_kb=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/max_hw_sectors_kb)
+	max_hw_bytes=$(( "$sysfs_max_hw_sectors_kb" * 1024 ))
+	sysfs_atomic_max_bytes=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/atomic_write_max_bytes)
+	sysfs_atomic_unit_max_bytes=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/atomic_write_unit_max_bytes)
+	sysfs_atomic_unit_min_bytes=$(cat /sys/block/"${SCSI_DEBUG_DEVICES[0]}"/queue/atomic_write_unit_min_bytes)
+	scsi_debug_atomic_wr_max_length=$(cat /sys/module/scsi_debug/parameters/atomic_wr_max_length)
+	scsi_debug_atomic_wr_gran=$(cat /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 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 1 - pass"
+	else
+		"TEST 1 - 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 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 2 - pass"
+		else
+			echo "TEST 2 - 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 2 - pass"
+		else
+			echo "TEST 2 - fail $scsi_atomic_max_bytes - $max_hw_bytes -" \
+				"$sysfs_atomic_max_bytes"
+		fi
+	fi
+
+	# 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 3 - pass"
+	else
+		echo "TEST 3 - fail $sysfs_atomic_unit_max_bytes - $scsi_atomic_max_bytes"
+	fi
+
+	# 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 4 - pass"
+	else
+		echo "TEST 4 - fail $sysfs_atomic_unit_min_bytes - $scsi_atomic_min_bytes"
+	fi
+
+	# TEST 5 - check statx stx_atomic_write_unit_min
+	statx_atomic_min=$(run_xfs_io_xstat "$dev" "stat.atomic_write_unit_min")
+	if [ "$statx_atomic_min" = "$scsi_atomic_min_bytes" ]
+	then
+		echo "TEST 5 - pass"
+	else
+		echo "TEST 5 - fail $statx_atomic_min - $scsi_atomic_min_bytes"
+	fi
+
+	# TEST  6 - check statx stx_atomic_write_unit_max
+	statx_atomic_max=$(run_xfs_io_xstat "$dev" "stat.atomic_write_unit_max")
+	if [ "$statx_atomic_max" = "$sysfs_atomic_unit_max_bytes" ]
+	then
+		echo "TEST 6 - pass"
+	else
+		echo "TEST 6 - fail $statx_atomic_max - $sysfs_atomic_unit_max_bytes"
+	fi
+
+	# TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with no RWF_ATOMIC flag - pwritev2 should
+	# be succesful.
+	bytes_written=$(run_xfs_io_pwritev2 "$dev" "$sysfs_atomic_unit_max_bytes")
+	if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ]
+	then
+		echo "TEST 7 - pass"
+	else
+		echo "TEST 7 - fail $bytes_written - $sysfs_atomic_unit_max_bytes"
+	fi
+
+	# TEST 8 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should
+	# be succesful.
+	bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$sysfs_atomic_unit_max_bytes")
+	if [ "$bytes_written" = "$sysfs_atomic_unit_max_bytes" ]
+	then
+		echo "TEST 8 - pass"
+	else
+		echo "TEST 8 - fail $bytes_written - $sysfs_atomic_unit_max_bytes"
+	fi
+
+	# TEST 9 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 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 "$dev" "$bytes_to_write")
+	if [ "$bytes_written" = "$bytes_to_write" ]
+	then
+		echo "TEST 9 - pass"
+	else
+		echo "TEST 9 - fail $bytes_written - $bytes_to_write"
+	fi
+
+	# TEST 10 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + 512 bytes with RWF_ATOMIC flag - pwritev2
+	# should not be succesful.
+	bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$bytes_to_write")
+	if [ "$bytes_written" = "" ]
+	then
+		echo "TEST 10 - pass"
+	else
+		echo "TEST 10 - fail $bytes_written - $bytes_to_write"
+	fi
+
+	# TEST 11 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with no RWF_ATOMIC flag - pwritev2 should
+	# be succesful.
+	bytes_written=$(run_xfs_io_pwritev2 "$dev" "$sysfs_atomic_unit_min_bytes")
+	if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ]
+	then
+		echo "TEST 11 - pass"
+	else
+		echo "TEST 11 - fail $bytes_written - $scsi_atomic_min_bytes"
+	fi
+
+	# TEST 12 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with RWF_ATOMIC flag - pwritev2 should
+	# be succesful.
+	bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$sysfs_atomic_unit_min_bytes")
+	if [ "$bytes_written" = "$sysfs_atomic_unit_min_bytes" ]
+	then
+		echo "TEST 12 - pass"
+	else
+		echo "TEST 12 - fail $bytes_written - $scsi_atomic_min_bytes"
+	fi
+
+	# 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.
+	# TEST 14 - perform a pwritev2 with a size of sysfs_atomic_unit_min_bytes - 512 bytes with
+        # RWF_ATOMIC flag - pwritev2 should fail.
+	bytes_to_write=$(( "${sysfs_atomic_unit_min_bytes}" - "${sysfs_logical_block_size}" ))
+	if [ "$bytes_to_write" = 0 ]
+	then
+		# sysfs_atomic_unit_min_bytes is set to 1 logical block so these tests aren't needed.
+		echo "TEST 13 - pass"
+		echo "TEST 14 - pass"
+	else
+		bytes_written=$(run_xfs_io_pwritev2 "$dev" "$bytes_to_write")
+		if [ "$bytes_written" = "$bytes_to_write" ]
+		then
+			echo "TEST 13 - pass"
+		else
+			echo "TEST 13 - fail $bytes_written - $bytes_to_write"
+		fi
+		bytes_written=$(run_xfs_io_pwritev2_atomic "$dev" "$bytes_to_write")
+		if [ "$bytes_written" = "" ]
+		then
+			echo "TEST 14 - pass"
+		else
+			echo "TEST 14 - 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..3a3382b1190c
--- /dev/null
+++ b/tests/scsi/009.out
@@ -0,0 +1,18 @@ 
+Running scsi/009
+TEST 1 - pass
+TEST 2 - pass
+TEST 3 - pass
+TEST 4 - pass
+TEST 5 - pass
+TEST 6 - pass
+TEST 7 - pass
+TEST 8 - pass
+TEST 9 - pass
+pwrite: Invalid argument
+TEST 10 - pass
+TEST 11 - pass
+TEST 12 - pass
+TEST 13 - pass
+pwrite: Invalid argument
+TEST 14 - pass
+Test complete