Skip to content

Commit 6e5dbe1

Browse files
Copilotigaw
andauthored
tests: skip 16-bit guard copy tests when namespace is in 64-bit guard PI mode
When ns_mgmt_supported=False, TestNVMe.setUp/tearDown never touch the namespace. If the device is configured with 64-bit guard PI (e.g. QEMU started with pif=2, or namespace left reformatted by a previous run), copy descriptor format 0 and format 2 commands would fail with NVMe status "Invalid Format" instead of being skipped cleanly. Add two helpers to TestNVMeCopy: - _get_current_ns_pif(): reads flbas from id-ns to determine the active lbaf index (NVMe spec FLBAS bit-field encoding), then looks up pif from the corresponding nvm-id-ns elbaf entry. - _check_16b_guard_ns(): calls skipTest if ns_mgmt is unavailable and the active namespace PI format is not 16-bit guard (pif != 0). Wire the check into: - TestNVMeCopyFormat0.setUp() (new setUp override) - TestNVMeCopyFormat23.test_copy_format_2() - TestNVMeCopyFormat23.test_copy_format_2_sopts() When ns_mgmt IS supported, TestNVMe.setUp() already recreates the namespace with flbas=0 (no metadata/PI), so the check is a no-op. Agent-Logs-Url: https://github.com/igaw/nvme-cli/sessions/c4376a88-dd31-47dc-b3d2-b6ad16fc190c Co-authored-by: igaw <1050803+igaw@users.noreply.github.com>
1 parent 487fa3f commit 6e5dbe1

1 file changed

Lines changed: 61 additions & 1 deletion

File tree

tests/nvme_copy_test.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,55 @@ def _check_ns_copy_limits(self):
8787
if missing:
8888
self.skipTest(f"{', '.join(missing)} are 0, copy not supported on this namespace")
8989

90+
def _get_current_ns_pif(self):
91+
"""
92+
Return the Protection Information Format (pif) of the currently active
93+
LBA format on self.ns1.
94+
95+
Reads the raw ``flbas`` byte from ``id-ns`` to determine the active
96+
lbaf index (NVMe spec: bits[3:0] are lbaf_index[3:0], bits[6:5] are
97+
lbaf_index[5:4]), then looks up that entry in the ``nvm-id-ns`` elbafs
98+
array. Returns 0 if either command fails or the pif field is absent
99+
(0 = 16-bit guard / no PI, the safe default for format 0/2 copy).
100+
"""
101+
id_ns_cmd = f"{self.nvme_bin} id-ns {self.ns1} --output-format=json"
102+
result = self.run_cmd(id_ns_cmd)
103+
if result.returncode != 0:
104+
return 0
105+
flbas = int(json.loads(result.stdout).get("flbas", 0))
106+
# NVMe spec FLBAS encoding: bits[3:0] = lbaf_index[3:0],
107+
# bits[6:5] = lbaf_index[5:4] (for extended LBA formats, NVMe 2.0+)
108+
lbaf_idx = (flbas & 0xF) | (((flbas >> 5) & 0x3) << 4)
109+
110+
nvm_id_ns_cmd = f"{self.nvme_bin} nvm-id-ns {self.ns1} --output-format=json"
111+
result = self.run_cmd(nvm_id_ns_cmd)
112+
if result.returncode != 0:
113+
return 0
114+
elbafs = json.loads(result.stdout).get("elbafs", [])
115+
if lbaf_idx < len(elbafs):
116+
return elbafs[lbaf_idx].get("pif", 0)
117+
return 0
118+
119+
def _check_16b_guard_ns(self):
120+
"""
121+
Skip the test if the current namespace uses a non-16-bit-guard PI
122+
format and namespace management is not available to restore it.
123+
124+
Copy descriptor formats 0 and 2 require the namespace to use 16-bit
125+
guard PI (pif=0) or no PI. When namespace management is supported,
126+
TestNVMe.setUp() already recreates the namespace with flbas=0 (no
127+
metadata, no PI), so this is a no-op in that case. When namespace
128+
management is not available and the namespace is already in a 64-bit
129+
guard PI format (e.g. QEMU started with pif=2, or left over from a
130+
previous test run), the copy command would fail with "Invalid Format"
131+
rather than being skipped cleanly.
132+
"""
133+
if not self.ns_mgmt_supported and self._get_current_ns_pif() != 0:
134+
self.skipTest(
135+
"current namespace uses non-16-bit-guard PI and namespace "
136+
"management is not supported; cannot run 16-bit guard copy test"
137+
)
138+
90139
def _find_64b_guard_lbaf_index(self):
91140
"""
92141
Find an LBA format index suitable for 64-bit guard PI (pif == 2).
@@ -118,6 +167,8 @@ def _find_64b_guard_lbaf_index(self):
118167
if result.returncode == 0:
119168
lbafs = json.loads(result.stdout).get("lbafs", [])
120169
for i, lbaf in enumerate(lbafs):
170+
# 64-bit guard PI (8B CRC-64 + 2B AppTag + 6B RefTag) needs
171+
# at least 16 bytes of metadata per QEMU docs.
121172
if int(lbaf.get("ms", 0)) >= 16:
122173
return i
123174
return None
@@ -237,9 +288,16 @@ class TestNVMeCopyFormat0(TestNVMeCopy):
237288
NVMe Copy tests using Descriptor Format 0.
238289
239290
Format 0 uses 16-bit guard PI and copies within a single namespace.
240-
No special namespace formatting is required.
291+
No special namespace formatting is required; the test is skipped if the
292+
current namespace is already using a non-16-bit-guard PI format and
293+
namespace management is not available to restore it.
241294
"""
242295

296+
def setUp(self):
297+
""" Pre Section for TestNVMeCopyFormat0 """
298+
super().setUp()
299+
self._check_16b_guard_ns()
300+
243301
def test_copy_format_0(self):
244302
""" Test copy with descriptor format 0 """
245303
self._check_format_supported(0)
@@ -297,13 +355,15 @@ def _run_format_3_copy(self, **kwargs):
297355
def test_copy_format_2(self):
298356
""" Test copy with descriptor format 2 """
299357
self._check_format_supported(2)
358+
self._check_16b_guard_ns()
300359
self._check_ns_copy_limits()
301360
self._enable_cdfe_for_format(2)
302361
self.copy(0, 1, 2, descriptor_format=2, snsids=self.ns1_nsid)
303362

304363
def test_copy_format_2_sopts(self):
305364
""" Test copy with descriptor format 2 and source options """
306365
self._check_format_supported(2)
366+
self._check_16b_guard_ns()
307367
self._check_ns_copy_limits()
308368
self._enable_cdfe_for_format(2)
309369
self.copy(0, 1, 2, descriptor_format=2, snsids=self.ns1_nsid, sopts=0)

0 commit comments

Comments
 (0)