From a1b0feaadbd3e7101b0e93dfcaccf79c1a69aaaa Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 20 May 2025 22:03:01 +0200 Subject: [PATCH] storage: Notify readiness as soon as the disk scheme has been created This prevents boot hangs when the disk driver hangs between creating the disk scheme and being fully initialized, while still preventing race conditions. --- Cargo.lock | 1 + storage/ahcid/src/main.rs | 3 +-- storage/bcm2835-sdhcid/src/main.rs | 2 +- storage/driver-block/Cargo.toml | 1 + storage/driver-block/src/lib.rs | 5 +++++ storage/ided/src/main.rs | 3 +-- storage/lived/src/main.rs | 3 +-- storage/nvmed/src/main.rs | 21 ++++++++++----------- storage/usbscsid/src/main.rs | 2 ++ storage/virtio-blkd/src/main.rs | 7 +++---- 10 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 851563d12f..a3fd0ece1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -390,6 +390,7 @@ dependencies = [ "libredox", "log", "partitionlib", + "redox-daemon", "redox-scheme 0.5.0", "redox_syscall", ] diff --git a/storage/ahcid/src/main.rs b/storage/ahcid/src/main.rs index d6b9f83d1c..7108647bf7 100644 --- a/storage/ahcid/src/main.rs +++ b/storage/ahcid/src/main.rs @@ -45,6 +45,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let scheme_name = format!("disk.{}", name); let mut scheme = DiskScheme::new( + Some(daemon), scheme_name, disks .into_iter() @@ -68,8 +69,6 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { .subscribe(irq_fd, 1, EventFlags::READ) .expect("ahcid: failed to event irq scheme"); - daemon.ready().expect("ahcid: failed to notify parent"); - for event in event_queue { let event = event.unwrap(); if event.fd == scheme.event_handle().raw() { diff --git a/storage/bcm2835-sdhcid/src/main.rs b/storage/bcm2835-sdhcid/src/main.rs index fda44f8860..0bfcea69da 100644 --- a/storage/bcm2835-sdhcid/src/main.rs +++ b/storage/bcm2835-sdhcid/src/main.rs @@ -101,6 +101,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let mut disks = Vec::new(); disks.push(sdhci); let mut scheme = DiskScheme::new( + Some(daemon), "disk.mmc".to_string(), disks .into_iter() @@ -116,7 +117,6 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { .expect("mmcd: failed to event disk scheme"); libredox::call::setrens(0, 0).expect("mmcd: failed to enter null namespace"); - daemon.ready().expect("mmcd: failed to notify parent"); for event in event_queue { let event = event.unwrap(); diff --git a/storage/driver-block/Cargo.toml b/storage/driver-block/Cargo.toml index da969a41c8..8f465cd535 100644 --- a/storage/driver-block/Cargo.toml +++ b/storage/driver-block/Cargo.toml @@ -13,5 +13,6 @@ log = "0.4" # TODO: migrate virtio to our executor futures = { version = "0.3.28", features = ["executor"] } +redox-daemon = "0.1" redox_syscall = { version = "0.5", features = ["std"] } redox-scheme = "0.5" diff --git a/storage/driver-block/src/lib.rs b/storage/driver-block/src/lib.rs index 0363228587..29cf01eda0 100644 --- a/storage/driver-block/src/lib.rs +++ b/storage/driver-block/src/lib.rs @@ -305,6 +305,7 @@ impl ExecutorTrait for TrivialExecutor { impl DiskScheme { pub fn new( + daemon: Option, scheme_name: String, disks: BTreeMap, executor: &impl ExecutorTrait, @@ -312,6 +313,10 @@ impl DiskScheme { assert!(scheme_name.starts_with("disk")); let socket = Socket::nonblock(&scheme_name).expect("failed to create disk scheme"); + if let Some(daemon) = daemon { + daemon.ready().expect("failed to signal readiness"); + } + Self { scheme_name, socket, diff --git a/storage/ided/src/main.rs b/storage/ided/src/main.rs index d3509a1ba8..db96961807 100644 --- a/storage/ided/src/main.rs +++ b/storage/ided/src/main.rs @@ -209,6 +209,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let scheme_name = format!("disk.{}", name); let mut scheme = DiskScheme::new( + Some(daemon), scheme_name, disks .into_iter() @@ -240,8 +241,6 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { libredox::call::setrens(0, 0).expect("ided: failed to enter null namespace"); - daemon.ready().expect("ided: failed to notify parent"); - event_queue .subscribe(scheme.event_handle().raw(), 0, EventFlags::READ) .expect("ided: failed to event disk scheme"); diff --git a/storage/lived/src/main.rs b/storage/lived/src/main.rs index b53452e779..f05950222e 100644 --- a/storage/lived/src/main.rs +++ b/storage/lived/src/main.rs @@ -121,6 +121,7 @@ fn main() -> anyhow::Result<()> { }; let mut scheme = DiskScheme::new( + Some(daemon), "disk.live".to_owned(), BTreeMap::from([( 0, @@ -142,8 +143,6 @@ fn main() -> anyhow::Result<()> { ) .unwrap(); - daemon.ready().expect("failed to signal readiness"); - for event in event_queue { match event.unwrap().user_data { Event::Scheme => TrivialExecutor.block_on(scheme.tick()).unwrap(), diff --git a/storage/nvmed/src/main.rs b/storage/nvmed/src/main.rs index e35df00629..6966570a52 100644 --- a/storage/nvmed/src/main.rs +++ b/storage/nvmed/src/main.rs @@ -174,7 +174,10 @@ impl Disk for NvmeDisk { fn time_arm(time_handle: &mut File, secs: i64) -> io::Result<()> { let mut time_buf = [0_u8; core::mem::size_of::()]; if time_handle.read(&mut time_buf)? < time_buf.len() { - return Err(io::Error::new(io::ErrorKind::InvalidData, "time read too small")); + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "time read too small", + )); } match libredox::data::timespec_from_mut_bytes(&mut time_buf) { @@ -231,10 +234,9 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let mut time_handle = File::open(&format!("/scheme/time/{}", libredox::flag::CLOCK_MONOTONIC)) .expect("failed to open time handle"); - let mut time_events = Box::pin(executor.register_external_event( - time_handle.as_raw_fd() as usize, - event::EventFlags::READ, - )); + let mut time_events = Box::pin( + executor.register_external_event(time_handle.as_raw_fd() as usize, event::EventFlags::READ), + ); // Try to init namespaces for 5 seconds time_arm(&mut time_handle, 5).expect("failed to arm timer"); @@ -243,17 +245,15 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { let time_future = time_events.as_mut().next(); futures::pin_mut!(namespaces_future); futures::pin_mut!(time_future); - match futures::future::select( - namespaces_future, - time_future, - ).await { + match futures::future::select(namespaces_future, time_future).await { futures::future::Either::Left((namespaces, _)) => namespaces, - futures::future::Either::Right(_) => panic!("timeout on init") + futures::future::Either::Right(_) => panic!("timeout on init"), } }); log::debug!("Initialized!"); let scheme = Rc::new(RefCell::new(DiskScheme::new( + Some(daemon), scheme_name, namespaces .into_iter() @@ -269,7 +269,6 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { .collect(), &*executor, ))); - daemon.ready().expect("nvmed: failed to signal readiness"); let mut scheme_events = Box::pin(executor.register_external_event( scheme.borrow().event_handle().raw(), diff --git a/storage/usbscsid/src/main.rs b/storage/usbscsid/src/main.rs index 6da8c36fe6..bc6d993a5e 100644 --- a/storage/usbscsid/src/main.rs +++ b/storage/usbscsid/src/main.rs @@ -42,6 +42,7 @@ fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: PortId, protocol: // TODO: Use eventfds. let handle = XhciClientHandle::new(scheme.to_owned(), port); + // FIXME should this wait notifying readiness until the disk scheme is created? daemon.ready().expect("usbscsid: failed to signal rediness"); let desc = handle @@ -98,6 +99,7 @@ fn daemon(daemon: redox_daemon::Daemon, scheme: String, port: PortId, protocol: }; let mut scheme = DiskScheme::new( + None, disk_scheme_name, BTreeMap::from([( 0, diff --git a/storage/virtio-blkd/src/main.rs b/storage/virtio-blkd/src/main.rs index 88fbb52bdf..253eb9c572 100644 --- a/storage/virtio-blkd/src/main.rs +++ b/storage/virtio-blkd/src/main.rs @@ -109,7 +109,7 @@ pub struct BlockVirtRequest { const_assert_eq!(core::mem::size_of::(), 16); -fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> { +fn daemon(daemon: redox_daemon::Daemon) -> anyhow::Result<()> { let mut pcid_handle = PciFunctionHandle::connect_default(); // Double check that we have the right device. @@ -152,6 +152,7 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> { }; let mut scheme = DiskScheme::new( + Some(daemon), scheme_name, BTreeMap::from([(0, VirtioDisk::new(queue, device_space))]), &driver_block::FuturesExecutor, @@ -167,8 +168,6 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> { ) .unwrap(); - deamon.ready().expect("virtio-blkd: failed to deamonize"); - for event in event_queue { match event.unwrap().user_data { Event::Scheme => futures::executor::block_on(scheme.tick()).unwrap(), @@ -179,6 +178,6 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> { } fn daemon_runner(redox_daemon: redox_daemon::Daemon) -> ! { - deamon(redox_daemon).unwrap(); + daemon(redox_daemon).unwrap(); unreachable!(); }