mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-09-03 18:04:16 +00:00
agent: handle hotplug virtio-mmio device
As dragonball support hotplug virtio-mmio device, we should handle it in agent Fixes:#5375 Signed-off-by: Zhongtao Hu <zhongtaohu.tim@linux.alibaba.com> Signed-off-by: alex.lyn <alex.lyn@antgroup.com>
This commit is contained in:
@@ -34,7 +34,7 @@ macro_rules! sl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const VM_ROOTFS: &str = "/";
|
const VM_ROOTFS: &str = "/";
|
||||||
|
const BLOCK: &str = "block";
|
||||||
pub const DRIVER_9P_TYPE: &str = "9p";
|
pub const DRIVER_9P_TYPE: &str = "9p";
|
||||||
pub const DRIVER_VIRTIOFS_TYPE: &str = "virtio-fs";
|
pub const DRIVER_VIRTIOFS_TYPE: &str = "virtio-fs";
|
||||||
pub const DRIVER_BLK_TYPE: &str = "blk";
|
pub const DRIVER_BLK_TYPE: &str = "blk";
|
||||||
@@ -204,7 +204,7 @@ impl ScsiBlockMatcher {
|
|||||||
|
|
||||||
impl UeventMatcher for ScsiBlockMatcher {
|
impl UeventMatcher for ScsiBlockMatcher {
|
||||||
fn is_match(&self, uev: &Uevent) -> bool {
|
fn is_match(&self, uev: &Uevent) -> bool {
|
||||||
uev.subsystem == "block" && uev.devpath.contains(&self.search) && !uev.devname.is_empty()
|
uev.subsystem == BLOCK && uev.devpath.contains(&self.search) && !uev.devname.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ impl VirtioBlkPciMatcher {
|
|||||||
|
|
||||||
impl UeventMatcher for VirtioBlkPciMatcher {
|
impl UeventMatcher for VirtioBlkPciMatcher {
|
||||||
fn is_match(&self, uev: &Uevent) -> bool {
|
fn is_match(&self, uev: &Uevent) -> bool {
|
||||||
uev.subsystem == "block" && self.rex.is_match(&uev.devpath) && !uev.devname.is_empty()
|
uev.subsystem == BLOCK && self.rex.is_match(&uev.devpath) && !uev.devname.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@ impl PmemBlockMatcher {
|
|||||||
|
|
||||||
impl UeventMatcher for PmemBlockMatcher {
|
impl UeventMatcher for PmemBlockMatcher {
|
||||||
fn is_match(&self, uev: &Uevent) -> bool {
|
fn is_match(&self, uev: &Uevent) -> bool {
|
||||||
uev.subsystem == "block"
|
uev.subsystem == BLOCK
|
||||||
&& uev.devpath.starts_with(ACPI_DEV_PATH)
|
&& uev.devpath.starts_with(ACPI_DEV_PATH)
|
||||||
&& uev.devpath.ends_with(&self.suffix)
|
&& uev.devpath.ends_with(&self.suffix)
|
||||||
&& !uev.devname.is_empty()
|
&& !uev.devname.is_empty()
|
||||||
@@ -441,6 +441,48 @@ async fn wait_for_ap_device(sandbox: &Arc<Mutex<Sandbox>>, address: ap::Address)
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MmioBlockMatcher {
|
||||||
|
suffix: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MmioBlockMatcher {
|
||||||
|
fn new(devname: &str) -> MmioBlockMatcher {
|
||||||
|
MmioBlockMatcher {
|
||||||
|
suffix: format!(r"/block/{}", devname),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UeventMatcher for MmioBlockMatcher {
|
||||||
|
fn is_match(&self, uev: &Uevent) -> bool {
|
||||||
|
uev.subsystem == BLOCK && uev.devpath.ends_with(&self.suffix) && !uev.devname.is_empty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub async fn get_virtio_mmio_device_name(
|
||||||
|
sandbox: &Arc<Mutex<Sandbox>>,
|
||||||
|
devpath: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
let devname = devpath
|
||||||
|
.strip_prefix("/dev/")
|
||||||
|
.ok_or_else(|| anyhow!("Storage source '{}' must start with /dev/", devpath))?;
|
||||||
|
|
||||||
|
let matcher = MmioBlockMatcher::new(devname);
|
||||||
|
let uev = wait_for_uevent(sandbox, matcher)
|
||||||
|
.await
|
||||||
|
.context("failed to wait for uevent")?;
|
||||||
|
if uev.devname != devname {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Unexpected device name {} for mmio device (expected {})",
|
||||||
|
uev.devname,
|
||||||
|
devname
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Scan SCSI bus for the given SCSI address(SCSI-Id and LUN)
|
/// Scan SCSI bus for the given SCSI address(SCSI-Id and LUN)
|
||||||
#[instrument]
|
#[instrument]
|
||||||
fn scan_scsi_bus(scsi_addr: &str) -> Result<()> {
|
fn scan_scsi_bus(scsi_addr: &str) -> Result<()> {
|
||||||
@@ -676,12 +718,18 @@ pub fn update_env_pci(
|
|||||||
#[instrument]
|
#[instrument]
|
||||||
async fn virtiommio_blk_device_handler(
|
async fn virtiommio_blk_device_handler(
|
||||||
device: &Device,
|
device: &Device,
|
||||||
_sandbox: &Arc<Mutex<Sandbox>>,
|
sandbox: &Arc<Mutex<Sandbox>>,
|
||||||
) -> Result<SpecUpdate> {
|
) -> Result<SpecUpdate> {
|
||||||
if device.vm_path.is_empty() {
|
if device.vm_path.is_empty() {
|
||||||
return Err(anyhow!("Invalid path for virtio mmio blk device"));
|
return Err(anyhow!("Invalid path for virtio mmio blk device"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !Path::new(&device.vm_path).exists() {
|
||||||
|
get_virtio_mmio_device_name(sandbox, &device.vm_path.to_string())
|
||||||
|
.await
|
||||||
|
.context("failed to get mmio device name")?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(DevNumUpdate::from_vm_path(&device.vm_path)?.into())
|
Ok(DevNumUpdate::from_vm_path(&device.vm_path)?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1394,7 +1442,7 @@ mod tests {
|
|||||||
|
|
||||||
let mut uev = crate::uevent::Uevent::default();
|
let mut uev = crate::uevent::Uevent::default();
|
||||||
uev.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
uev.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
||||||
uev.subsystem = "block".to_string();
|
uev.subsystem = BLOCK.to_string();
|
||||||
uev.devpath = devpath.clone();
|
uev.devpath = devpath.clone();
|
||||||
uev.devname = devname.to_string();
|
uev.devname = devname.to_string();
|
||||||
|
|
||||||
@@ -1428,7 +1476,7 @@ mod tests {
|
|||||||
let mut uev_a = crate::uevent::Uevent::default();
|
let mut uev_a = crate::uevent::Uevent::default();
|
||||||
let relpath_a = "/0000:00:0a.0";
|
let relpath_a = "/0000:00:0a.0";
|
||||||
uev_a.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
uev_a.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
||||||
uev_a.subsystem = "block".to_string();
|
uev_a.subsystem = BLOCK.to_string();
|
||||||
uev_a.devname = devname.to_string();
|
uev_a.devname = devname.to_string();
|
||||||
uev_a.devpath = format!("{}{}/virtio4/block/{}", root_bus, relpath_a, devname);
|
uev_a.devpath = format!("{}{}/virtio4/block/{}", root_bus, relpath_a, devname);
|
||||||
let matcher_a = VirtioBlkPciMatcher::new(relpath_a);
|
let matcher_a = VirtioBlkPciMatcher::new(relpath_a);
|
||||||
@@ -1512,7 +1560,7 @@ mod tests {
|
|||||||
let mut uev_a = crate::uevent::Uevent::default();
|
let mut uev_a = crate::uevent::Uevent::default();
|
||||||
let addr_a = "0:0";
|
let addr_a = "0:0";
|
||||||
uev_a.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
uev_a.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
||||||
uev_a.subsystem = "block".to_string();
|
uev_a.subsystem = BLOCK.to_string();
|
||||||
uev_a.devname = devname.to_string();
|
uev_a.devname = devname.to_string();
|
||||||
uev_a.devpath = format!(
|
uev_a.devpath = format!(
|
||||||
"{}/0000:00:00.0/virtio0/host0/target0:0:0/0:0:{}/block/sda",
|
"{}/0000:00:00.0/virtio0/host0/target0:0:0/0:0:{}/block/sda",
|
||||||
@@ -1555,6 +1603,33 @@ mod tests {
|
|||||||
assert!(!matcher_a.is_match(&uev_b));
|
assert!(!matcher_a.is_match(&uev_b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_mmio_block_matcher() {
|
||||||
|
let devname_a = "vda";
|
||||||
|
let devname_b = "vdb";
|
||||||
|
let mut uev_a = crate::uevent::Uevent::default();
|
||||||
|
uev_a.action = crate::linux_abi::U_EVENT_ACTION_ADD.to_string();
|
||||||
|
uev_a.subsystem = BLOCK.to_string();
|
||||||
|
uev_a.devname = devname_a.to_string();
|
||||||
|
uev_a.devpath = format!(
|
||||||
|
"/sys/devices/virtio-mmio-cmdline/virtio-mmio.0/virtio0/block/{}",
|
||||||
|
devname_a
|
||||||
|
);
|
||||||
|
let matcher_a = MmioBlockMatcher::new(devname_a);
|
||||||
|
|
||||||
|
let mut uev_b = uev_a.clone();
|
||||||
|
uev_b.devpath = format!(
|
||||||
|
"/sys/devices/virtio-mmio-cmdline/virtio-mmio.4/virtio4/block/{}",
|
||||||
|
devname_b
|
||||||
|
);
|
||||||
|
let matcher_b = MmioBlockMatcher::new(devname_b);
|
||||||
|
|
||||||
|
assert!(matcher_a.is_match(&uev_a));
|
||||||
|
assert!(matcher_b.is_match(&uev_b));
|
||||||
|
assert!(!matcher_b.is_match(&uev_a));
|
||||||
|
assert!(!matcher_a.is_match(&uev_b));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_split_vfio_pci_option() {
|
fn test_split_vfio_pci_option() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@@ -21,10 +21,11 @@ use nix::unistd::{Gid, Uid};
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::device::{
|
use crate::device::{
|
||||||
get_scsi_device_name, get_virtio_blk_pci_device_name, online_device, wait_for_pmem_device,
|
get_scsi_device_name, get_virtio_blk_pci_device_name, get_virtio_mmio_device_name,
|
||||||
DRIVER_9P_TYPE, DRIVER_BLK_CCW_TYPE, DRIVER_BLK_TYPE, DRIVER_EPHEMERAL_TYPE, DRIVER_LOCAL_TYPE,
|
online_device, wait_for_pmem_device, DRIVER_9P_TYPE, DRIVER_BLK_CCW_TYPE, DRIVER_BLK_TYPE,
|
||||||
DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE, DRIVER_OVERLAYFS_TYPE, DRIVER_SCSI_TYPE,
|
DRIVER_EPHEMERAL_TYPE, DRIVER_LOCAL_TYPE, DRIVER_MMIO_BLK_TYPE, DRIVER_NVDIMM_TYPE,
|
||||||
DRIVER_VIRTIOFS_TYPE, DRIVER_WATCHABLE_BIND_TYPE, FS_TYPE_HUGETLB,
|
DRIVER_OVERLAYFS_TYPE, DRIVER_SCSI_TYPE, DRIVER_VIRTIOFS_TYPE, DRIVER_WATCHABLE_BIND_TYPE,
|
||||||
|
FS_TYPE_HUGETLB,
|
||||||
};
|
};
|
||||||
use crate::linux_abi::*;
|
use crate::linux_abi::*;
|
||||||
use crate::pci;
|
use crate::pci;
|
||||||
@@ -473,8 +474,14 @@ async fn virtiommio_blk_storage_handler(
|
|||||||
storage: &Storage,
|
storage: &Storage,
|
||||||
sandbox: Arc<Mutex<Sandbox>>,
|
sandbox: Arc<Mutex<Sandbox>>,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
let storage = storage.clone();
|
||||||
|
if !Path::new(&storage.source).exists() {
|
||||||
|
get_virtio_mmio_device_name(&sandbox, &storage.source)
|
||||||
|
.await
|
||||||
|
.context("failed to get mmio device name")?;
|
||||||
|
}
|
||||||
//The source path is VmPath
|
//The source path is VmPath
|
||||||
common_storage_handler(logger, storage)
|
common_storage_handler(logger, &storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtiofs_storage_handler handles the storage for virtio-fs.
|
// virtiofs_storage_handler handles the storage for virtio-fs.
|
||||||
|
Reference in New Issue
Block a user