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.
This commit is contained in:
bjorn3
2025-05-20 22:03:01 +02:00
parent 9403db2125
commit a1b0feaadb
10 changed files with 26 additions and 22 deletions
Generated
+1
View File
@@ -390,6 +390,7 @@ dependencies = [
"libredox",
"log",
"partitionlib",
"redox-daemon",
"redox-scheme 0.5.0",
"redox_syscall",
]
+1 -2
View File
@@ -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() {
+1 -1
View File
@@ -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();
+1
View File
@@ -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"
+5
View File
@@ -305,6 +305,7 @@ impl ExecutorTrait for TrivialExecutor {
impl<T: Disk> DiskScheme<T> {
pub fn new(
daemon: Option<redox_daemon::Daemon>,
scheme_name: String,
disks: BTreeMap<u32, T>,
executor: &impl ExecutorTrait,
@@ -312,6 +313,10 @@ impl<T: Disk> DiskScheme<T> {
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,
+1 -2
View File
@@ -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");
+1 -2
View File
@@ -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(),
+10 -11
View File
@@ -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::<libredox::data::TimeSpec>()];
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(),
+2
View File
@@ -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,
+3 -4
View File
@@ -109,7 +109,7 @@ pub struct BlockVirtRequest {
const_assert_eq!(core::mem::size_of::<BlockVirtRequest>(), 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!();
}