Merge pull request #11466 from lifupan/blockfile

runtime-rs: add the blockfile based rootfs support
This commit is contained in:
Alex Lyn 2025-06-25 09:46:54 +08:00 committed by GitHub
commit 648fef4f52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 6 deletions

View File

@ -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<u64> {
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,

View File

@ -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<dyn Rootfs> = 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")?,
);