Skip to content

Commit 2cc8e63

Browse files
committed
tests: Filter NVMe controllers by subsystem NQN for precise polling
Fixes #1080 Only wait for controllers matching the specific test subsystem NQN,improving timing reliability.
1 parent a21347f commit 2cc8e63

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

tests/nvme_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ def test_connect_multiple_ns(self):
416416
NUM_NS = 3
417417

418418
# test that no device node exists for given subsystem nqn
419-
ctrls = find_nvme_ctrl_devs_for_subnqn(self.SUBNQN)
419+
ctrls = find_nvme_ctrl_devs_for_subnqn(self.SUBNQN, wait_for_ready=False)
420420
self.assertEqual(len(ctrls), 0)
421421

422422
self._setup_target(NUM_NS)

tests/utils.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,48 @@ def clean_scsi_debug(scsi_debug_dev):
274274
except:
275275
pass
276276

277-
def find_nvme_ctrl_devs_for_subnqn(subnqn):
277+
def _wait_for_nvme_controllers_ready(subnqn, timeout=2):
278+
"""
279+
Wait for NVMe controllers with matching subsystem NQN to be in live state
280+
281+
:param str subnqn: subsystem nqn to match controllers against
282+
:param int timeout: timeout in seconds (default: 2)
283+
:returns: True if ready, False if timeout
284+
"""
285+
start_time = time.time()
286+
wait_time = 0.1 # Start with 100ms
287+
max_wait = 0.5 # Cap at 500ms
288+
289+
while time.time() - start_time < timeout:
290+
try:
291+
for ctrl_path in glob.glob("/sys/class/nvme/nvme*/"):
292+
state_file = os.path.join(ctrl_path, "state")
293+
subsysnqn_file = os.path.join(ctrl_path, "subsysnqn")
294+
try:
295+
state = read_file(state_file).strip()
296+
controller_subnqn = read_file(subsysnqn_file).strip()
297+
if state == "live" and controller_subnqn == subnqn:
298+
# Found a matching live controller, return immediately
299+
os.system("udevadm settle")
300+
return True
301+
except:
302+
continue
303+
304+
except:
305+
pass
306+
307+
time.sleep(wait_time)
308+
wait_time = min(wait_time * 1.2, max_wait) # Slower exponential backoff
309+
310+
os.system("udevadm settle")
311+
return False
312+
313+
def find_nvme_ctrl_devs_for_subnqn(subnqn, wait_for_ready=True):
278314
"""
279315
Find NVMe controller devices for the specified subsystem nqn
280316
281317
:param str subnqn: subsystem nqn
318+
:param bool wait_for_ready: whether to wait for controllers to be ready (default: True)
282319
"""
283320

284321
def _check_subsys(subsys, dev_paths):
@@ -295,6 +332,9 @@ def _check_subsys(subsys, dev_paths):
295332
except:
296333
pass
297334

335+
# Wait for controllers to be ready if requested
336+
if wait_for_ready:
337+
_wait_for_nvme_controllers_ready(subnqn)
298338
ret, out, err = run_command("nvme list --output-format=json --verbose")
299339
if ret != 0:
300340
raise RuntimeError("Error getting NVMe list: '%s %s'" % (out, err))
@@ -317,11 +357,12 @@ def _check_subsys(subsys, dev_paths):
317357
return dev_paths
318358

319359

320-
def find_nvme_ns_devs_for_subnqn(subnqn):
360+
def find_nvme_ns_devs_for_subnqn(subnqn, wait_for_ready=True):
321361
"""
322362
Find NVMe namespace block devices for the specified subsystem nqn
323363
324364
:param str subnqn: subsystem nqn
365+
:param bool wait_for_ready: whether to wait for controllers to be ready (default: True)
325366
"""
326367

327368
def _check_namespaces(node, ns_dev_paths):
@@ -344,6 +385,8 @@ def _check_subsys(subsys, ns_dev_paths):
344385
if 'Namespaces' in ctrl:
345386
_check_namespaces(ctrl, ns_dev_paths)
346387

388+
if wait_for_ready:
389+
_wait_for_nvme_controllers_ready(subnqn)
347390
ret, out, err = run_command("nvme list --output-format=json --verbose")
348391
if ret != 0:
349392
raise RuntimeError("Error getting NVMe list: '%s %s'" % (out, err))

0 commit comments

Comments
 (0)