diff --git a/local/recipes/system/driver-manager/source/src/config.rs b/local/recipes/system/driver-manager/source/src/config.rs index 83bcb52a7b..ec365b9d0b 100644 --- a/local/recipes/system/driver-manager/source/src/config.rs +++ b/local/recipes/system/driver-manager/source/src/config.rs @@ -259,20 +259,11 @@ impl Driver for DriverConfig { format!("/usr/lib/drivers/{}", self.command[0]) }; - // Also check the initfs path — drivers like nvmed live in - // /scheme/initfs/lib/drivers/ during early boot and may not yet - // be staged to /usr/lib/drivers/ after switchroot. - if !std::path::Path::new(&actual_path).exists() { - let initfs_path = format!("/scheme/initfs/lib/drivers/{}", self.command[0].rsplit('/').next().unwrap_or(&self.command[0])); - if std::path::Path::new(&initfs_path).exists() { - return ProbeResult::Deferred { - reason: format!("driver in initfs only (not yet in rootfs): {}", initfs_path), - }; - } - return ProbeResult::Fatal { - reason: format!("driver binary not found: {} (also checked {})", actual_path, initfs_path), - }; - } + // Skip the binary existence check. On Redox, scheme paths + // (especially /scheme/initfs/) may block on open/stat. The + // Command::new() spawn will fail with a clear error if the + // binary doesn't exist, which is handled as a Fatal probe + // result downstream. // Skip if this driver's scheme is already registered (e.g., by // pcid-spawner during initfs). Prevents re-spawning drivers diff --git a/local/recipes/system/driver-manager/source/src/main.rs b/local/recipes/system/driver-manager/source/src/main.rs index 035daae8ea..52d02cd4b5 100644 --- a/local/recipes/system/driver-manager/source/src/main.rs +++ b/local/recipes/system/driver-manager/source/src/main.rs @@ -420,7 +420,7 @@ fn main() { let manager_config = ManagerConfig { max_concurrent_probes: 4, deferred_retry_ms: 500, - async_probe: true, + async_probe: !initfs, }; let manager = Arc::new(Mutex::new(DeviceManager::new(manager_config.clone()))); @@ -498,7 +498,72 @@ fn main() { idle_forever(); } - let max_retries = if initfs { 10u32 } else { 3u32 }; + // In initfs mode: do bounded retries for deferred probes, then exit + // so init can proceed to rootfs mount. The rootfs driver-manager + // instance (started by the rootfs service) handles hotplug and + // persistent management. + if initfs { + let max_retries = 10u32; + for retry in 1..=max_retries { + if SHUTDOWN_REQUESTED.load(Ordering::SeqCst) { + log::info!("driver-manager: SIGTERM received, shutting down"); + graceful_shutdown(); + process::exit(0); + } + + reap_all_drivers(&driver_configs); + thread::sleep(Duration::from_millis(500)); + + let retry_events = match manager.lock() { + Ok(mut mgr) => mgr.retry_deferred(), + Err(err) => { + log::error!("failed to retry deferred probes: manager lock poisoned: {err}"); + break; + } + }; + + let mut remaining = 0; + let mut newly_bound = 0; + + for event in &retry_events { + log_timeline(event); + if let ProbeEvent::ProbeCompleted { + device, + driver_name, + result, + } = event + { + match result { + ProbeResult::Bound => { + newly_bound += 1; + notify_bound_device(scheme.as_ref(), device, driver_name); + } + ProbeResult::Deferred { .. } => remaining += 1, + _ => {} + } + } + } + + if remaining == 0 { + log::info!("all deferred resolved after {} retries (initfs)", retry); + break; + } + + if newly_bound > 0 { + log::info!( + "initfs retry #{}: {} new, {} remaining", + retry, + newly_bound, + remaining + ); + } + } + + log::info!("driver-manager: initfs phase complete, exiting"); + return; + } + + let max_retries = 3u32; for retry in 1..=max_retries { if SHUTDOWN_REQUESTED.load(Ordering::SeqCst) { log::info!("driver-manager: SIGTERM received during deferred retry, shutting down");