Skip to content

Commit

Permalink
nvme/059: add atomic write tests
Browse files Browse the repository at this point in the history
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 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

Signed-off-by: Alan Adamson <[email protected]>
Reviewed-by: Chaitanya Kulkarni <[email protected]>
Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
  • Loading branch information
alanpeterad authored and kawasaki committed Feb 20, 2025
1 parent 4e29bbe commit c37ab6f
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 0 deletions.
146 changes: 146 additions & 0 deletions tests/nvme/059
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#!/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 statx_atomic_min
local sysfs_atomic_max_bytes
local sysfs_atomic_unit_max_bytes
local sysfs_atomic_unit_min_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 - Verify statx is correctly reporting atomic_unit_min_bytes"
statx_atomic_max=$(run_xfs_io_xstat /dev/"$ns_dev" "stat.atomic_write_unit_min")
if [ "$sysfs_atomic_unit_min_bytes" = "$statx_atomic_max" ]
then
echo "$test_desc - pass"
else
echo "$test_desc - fail $statx_atomic_min - $sysfs_atomic_unit_min_bytes"
fi

test_desc="TEST 5 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with "
test_desc+="RWF_ATOMIC flag - pwritev2 should be successful"
bytes_written=$(run_xfs_io_pwritev2_atomic /dev/"$ns_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 - $sysfs_atomic_unit_min_bytes"
fi

test_desc="TEST 6 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with "
test_desc+="RWF_ATOMIC flag - pwritev2 should be successful"
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 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + logical "
test_desc+="block with RWF_ATOMIC flag - pwritev2 should not be successful"
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"
}
9 changes: 9 additions & 0 deletions tests/nvme/059.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
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 - Verify statx is correctly reporting atomic_unit_min_bytes - pass
TEST 5 - perform a pwritev2 with size of sysfs_atomic_unit_min_bytes with RWF_ATOMIC flag - pwritev2 should be successful - pass
TEST 6 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes with RWF_ATOMIC flag - pwritev2 should be successful - pass
TEST 7 - perform a pwritev2 with size of sysfs_atomic_unit_max_bytes + logical block with RWF_ATOMIC flag - pwritev2 should not be successful - pass
Test complete

0 comments on commit c37ab6f

Please sign in to comment.