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:
Generated
+1
@@ -390,6 +390,7 @@ dependencies = [
|
||||
"libredox",
|
||||
"log",
|
||||
"partitionlib",
|
||||
"redox-daemon",
|
||||
"redox-scheme 0.5.0",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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!();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user