@@ -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