diff --git a/src/dmverity.rs b/src/dmverity.rs index 3c70658..5ce44a8 100644 --- a/src/dmverity.rs +++ b/src/dmverity.rs @@ -12,7 +12,7 @@ use nix::libc::dev_t; use nix::sys::stat::minor; use crate::cmdline::CmdlineOptions; -use crate::{read_file, Result}; +use crate::{read_file, wait_for_device, Result}; const DM_VERSION_MAJOR: u32 = 4; @@ -120,8 +120,9 @@ pub fn prepare_dmverity(options: &mut CmdlineOptions) -> Result { return Ok(false); } let root_device = options.root.as_ref().ok_or("No root device")?; - if !Path::new(&root_device).exists() { - return Ok(false); + match options.rootfstype.as_deref() { + Some("nfs") | Some("9p") => return Ok(false), + _ => wait_for_device(root_device)?, } let mut data_blocks = ""; diff --git a/src/main.rs b/src/main.rs index 13e79df..dd524bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,8 @@ use std::os::fd::{AsFd, AsRawFd, RawFd}; use std::os::unix::ffi::OsStrExt; use std::panic::set_hook; use std::path::Path; +use std::thread; +use std::time; use cmdline::{parse_cmdline, CmdlineOptions}; #[cfg(feature = "dmverity")] @@ -51,6 +53,21 @@ fn read_file(filename: &str) -> std::result::Result { read_to_string(filename).map_err(|e| format!("Failed to read {filename}: {e}")) } +fn wait_for_device(root_device: &str) -> Result<()> { + let duration = time::Duration::from_millis(5); + let path = Path::new(&root_device); + + for _ in 0..1000 { + if path.exists() { + return Ok(()); + } + + thread::sleep(duration); + } + + Err("timout reached while waiting for the device".into()) +} + /* * Setup stdout/stderr. The kernel will create /dev/console in the * initramfs, so we can use that. diff --git a/src/mount.rs b/src/mount.rs index 43a55f8..2e4525b 100644 --- a/src/mount.rs +++ b/src/mount.rs @@ -7,7 +7,7 @@ use log::debug; use nix::mount::{mount, MsFlags}; use crate::cmdline::CmdlineOptions; -use crate::{mkdir, Result}; +use crate::{mkdir, wait_for_device, Result}; pub fn do_mount( src: Option<&str>, @@ -45,10 +45,15 @@ pub fn mount_apivfs(dst: &str, fstype: &str) -> Result<()> { } pub fn mount_root(options: &CmdlineOptions) -> Result<()> { - if options.root.is_none() { - return Err("root= not found in /proc/cmdline".into()); + let root = options + .root + .as_ref() + .ok_or("root= not found in /proc/cmdline")?; + + match options.rootfstype.as_deref() { + Some("nfs") | Some("9p") => (), + _ => wait_for_device(root)?, } - mkdir("/root")?; debug!(