diff --git a/src/runtime-rs/crates/resource/src/rootfs/block_rootfs.rs b/src/runtime-rs/crates/resource/src/rootfs/block_rootfs.rs index 11e2994280..70b0ab7b79 100644 --- a/src/runtime-rs/crates/resource/src/rootfs/block_rootfs.rs +++ b/src/runtime-rs/crates/resource/src/rootfs/block_rootfs.rs @@ -25,6 +25,8 @@ use oci_spec::runtime as oci; use std::fs; use tokio::sync::RwLock; +const BLOCKFILE_ROOTFS_FLAG: &str = "loop"; + pub(crate) struct BlockRootfs { guest_path: String, device_id: String, @@ -53,6 +55,7 @@ impl BlockRootfs { major: stat::major(dev_id) as i64, minor: stat::minor(dev_id) as i64, driver_option: block_driver.clone(), + path_on_host: rootfs.source.clone(), ..Default::default() }; @@ -133,15 +136,40 @@ impl Rootfs for BlockRootfs { } } -pub(crate) fn is_block_rootfs(file: &str) -> Option { - if file.is_empty() { +pub(crate) fn is_block_rootfs(m: &Mount) -> Option<(u64, Mount)> { + if m.source.is_empty() { return None; } - match stat::stat(file) { + + match stat::stat(m.source.as_str()) { Ok(fstat) => { if SFlag::from_bits_truncate(fstat.st_mode) == SFlag::S_IFBLK { let dev_id = fstat.st_rdev; - return Some(dev_id); + let mut volume = m.clone(); + + //clear the volume resource thus the block device will use the dev_id + //to find the device's host path; + volume.source = String::new(); + return Some((dev_id, m.clone())); + } + + if SFlag::from_bits_truncate(fstat.st_mode) == SFlag::S_IFREG + && m.options.contains(&BLOCKFILE_ROOTFS_FLAG.to_string()) + { + //use the block file's inode as the device id, which can make sure it's unique. + let dev_id = fstat.st_ino; + let options = m + .options + .clone() + .into_iter() + .filter(|o| !o.eq(BLOCKFILE_ROOTFS_FLAG)) + .collect(); + + //discard the blockfile rootfs's mount option "loop" + let mut volume = m.clone(); + volume.options = options; + + return Some((dev_id, volume)); } } Err(_) => return None, diff --git a/src/runtime-rs/crates/resource/src/rootfs/mod.rs b/src/runtime-rs/crates/resource/src/rootfs/mod.rs index e0d34e22ba..334771f860 100644 --- a/src/runtime-rs/crates/resource/src/rootfs/mod.rs +++ b/src/runtime-rs/crates/resource/src/rootfs/mod.rs @@ -105,11 +105,11 @@ impl RootFsResource { return Ok(virtual_volume); } - let rootfs = if let Some(dev_id) = is_block_rootfs(&layer.source) { + let rootfs = if let Some((dev_id, layer)) = is_block_rootfs(layer) { // handle block rootfs info!(sl!(), "block device: {}", dev_id); let block_rootfs: Arc = Arc::new( - block_rootfs::BlockRootfs::new(device_manager, sid, cid, dev_id, layer) + block_rootfs::BlockRootfs::new(device_manager, sid, cid, dev_id, &layer) .await .context("new block rootfs")?, );