initfs: exit after enumeration, skip scheme path checks

- Skip binary existence check in probe(): Redox scheme paths
  (especially /scheme/initfs/) may block on open/stat indefinitely.
  Command::new() spawn fails cleanly if binary missing.
- In initfs mode: use synchronous probe, do bounded deferred
  retries, then exit. Rootfs instance handles hotplug.
- Avoids pcid config handle read hang that blocks async threads.
This commit is contained in:
2026-05-31 19:22:39 +03:00
parent 3431bbfeb2
commit cd05afdcb1
2 changed files with 72 additions and 16 deletions
@@ -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
@@ -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");