Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime-rs: bringing virtio-fs device in device-manager #7932

Merged
merged 3 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 7 additions & 3 deletions src/runtime-rs/crates/hypervisor/src/ch/inner_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::BlockDevice;
use crate::HybridVsockDevice;
use crate::NetworkConfig;
use crate::PciPath;
use crate::ShareFsConfig;
use crate::ShareFsDevice;
use crate::ShareFsDeviceConfig;
use crate::VfioDevice;
use crate::VmmState;
use anyhow::{anyhow, Context, Result};
Expand Down Expand Up @@ -108,6 +108,10 @@ impl CloudHypervisorInner {
}
}

pub(crate) async fn update_device(&mut self, _device: DeviceType) -> Result<()> {
Ok(())
}

async fn handle_share_fs_device(&mut self, sharefs: ShareFsDevice) -> Result<DeviceType> {
let device: ShareFsDevice = sharefs.clone();
if device.config.fs_type != VIRTIO_FS {
Expand Down Expand Up @@ -363,12 +367,12 @@ impl TryFrom<NetworkConfig> for NetConfig {
}
#[derive(Debug)]
pub struct ShareFsSettings {
cfg: ShareFsDeviceConfig,
cfg: ShareFsConfig,
vm_path: String,
}

impl ShareFsSettings {
pub fn new(cfg: ShareFsDeviceConfig, vm_path: String) -> Self {
pub fn new(cfg: ShareFsConfig, vm_path: String) -> Self {
ShareFsSettings { cfg, vm_path }
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/runtime-rs/crates/hypervisor/src/ch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ impl Hypervisor for CloudHypervisor {
inner.remove_device(device).await
}

async fn update_device(&self, device: DeviceType) -> Result<()> {
let mut inner = self.inner.write().await;
inner.update_device(device).await
}

async fn get_agent_socket(&self) -> Result<String> {
let inner = self.inner.write().await;
inner.get_agent_socket().await
Expand Down
94 changes: 92 additions & 2 deletions src/runtime-rs/crates/hypervisor/src/device/device_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use tokio::sync::{Mutex, RwLock};

use crate::{
vhost_user_blk::VhostUserBlkDevice, BlockConfig, BlockDevice, HybridVsockDevice, Hypervisor,
NetworkDevice, VfioDevice, VhostUserConfig, KATA_BLK_DEV_TYPE, KATA_MMIO_BLK_DEV_TYPE,
KATA_NVDIMM_DEV_TYPE, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM,
NetworkDevice, ShareFsDevice, VfioDevice, VhostUserConfig, KATA_BLK_DEV_TYPE,
KATA_MMIO_BLK_DEV_TYPE, KATA_NVDIMM_DEV_TYPE, VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM,
};

use super::{
Expand Down Expand Up @@ -226,6 +226,11 @@ impl DeviceManager {
return Some(device_id.to_string());
}
}
DeviceType::ShareFs(device) => {
if device.config.host_shared_path == host_path {
return Some(device_id.to_string());
}
}
_ => {
// TODO: support find other device type
continue;
Expand Down Expand Up @@ -325,6 +330,22 @@ impl DeviceManager {
// No need to do find device for hybrid vsock device.
Arc::new(Mutex::new(HybridVsockDevice::new(&device_id, hvconfig)))
}
DeviceConfig::ShareFsCfg(config) => {
// Try to find the sharefs device. If found, just return matched device id.
if let Some(device_id_matched) =
self.find_device(config.host_shared_path.clone()).await
{
info!(
sl!(),
"share-fs device with path:{:?} found, device id: {:?}",
config.host_shared_path,
device_id_matched
);
return Ok(device_id_matched);
}

Arc::new(Mutex::new(ShareFsDevice::new(&device_id, config)))
}
_ => {
return Err(anyhow!("invliad device type"));
}
Expand Down Expand Up @@ -437,6 +458,62 @@ impl DeviceManager {

Err(anyhow!("ID are exhausted"))
}

async fn try_update_device(&mut self, updated_config: &DeviceConfig) -> Result<()> {
let device_id = match updated_config {
DeviceConfig::ShareFsCfg(config) => {
// Try to find the sharefs device.
// If found, just return the matched device id, otherwise return an error.
if let Some(device_id_matched) =
self.find_device(config.host_shared_path.clone()).await
{
device_id_matched
} else {
return Err(anyhow!(
"no matching device was found to do the update operation"
));
}
}
// TODO for other Device Type
_ => {
return Err(anyhow!("update device with unsupported device type"));
}
};

// get the original device
let target_device = self
.get_device_info(&device_id)
.await
.context("get device failed")?;

// update device with the updated configuration.
let updated_device: ArcMutexDevice = match target_device {
DeviceType::ShareFs(mut device) => {
if let DeviceConfig::ShareFsCfg(config) = updated_config {
// update the mount_config.
device.config.mount_config = config.mount_config.clone();
}
Arc::new(Mutex::new(device))
}
_ => return Err(anyhow!("update unsupported device type")),
};

// do handle update
if let Err(e) = updated_device
.lock()
.await
.update(self.hypervisor.as_ref())
.await
{
debug!(sl!(), "update device with device id: {:?}", &device_id);
return Err(e);
}

// Finally, we update the Map in Device Manager
self.devices.insert(device_id, updated_device);

Ok(())
}
}

// Many scenarios have similar steps when adding devices. so to reduce duplicated code,
Expand Down Expand Up @@ -472,6 +549,19 @@ pub async fn do_handle_device(
Ok(device_info)
}

pub async fn do_update_device(
d: &RwLock<DeviceManager>,
updated_config: &DeviceConfig,
) -> Result<()> {
d.write()
.await
.try_update_device(updated_config)
.await
.context("failed to update device")?;

Ok(())
}

pub async fn get_block_driver(d: &RwLock<DeviceManager>) -> String {
d.read().await.get_block_driver().await
}
Expand Down
3 changes: 1 addition & 2 deletions src/runtime-rs/crates/hypervisor/src/device/driver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ pub use virtio_blk::{
VIRTIO_BLOCK_MMIO, VIRTIO_BLOCK_PCI, VIRTIO_PMEM,
};
pub use virtio_fs::{
ShareFsDevice, ShareFsDeviceConfig, ShareFsMountConfig, ShareFsMountDevice, ShareFsMountType,
ShareFsOperation,
ShareFsConfig, ShareFsDevice, ShareFsMountConfig, ShareFsMountOperation, ShareFsMountType,
};
pub use virtio_net::{Address, Backend, NetworkConfig, NetworkDevice};
pub use virtio_vsock::{
Expand Down
5 changes: 5 additions & 0 deletions src/runtime-rs/crates/hypervisor/src/device/driver/vfio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,11 @@ impl Device for VfioDevice {
Ok(device_index)
}

async fn update(&mut self, _h: &dyn hypervisor) -> Result<()> {
// There's no need to do update for vfio device
Ok(())
}

async fn increase_attach_count(&mut self) -> Result<bool> {
match self.attach_count {
0 => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ impl Device for VhostUserBlkDevice {
Ok(Some(self.config.index))
}

async fn update(&mut self, _h: &dyn hypervisor) -> Result<()> {
// There's no need to do update for vhost-user-blk
Ok(())
}

async fn get_device_info(&self) -> DeviceType {
DeviceType::VhostUserBlk(self.clone())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ impl Device for BlockDevice {
Ok(Some(self.config.index))
}

async fn update(&mut self, _h: &dyn hypervisor) -> Result<()> {
// There's no need to do update for virtio-blk
Ok(())
}

async fn get_device_info(&self) -> DeviceType {
DeviceType::Block(self.clone())
}
Expand Down
93 changes: 76 additions & 17 deletions src/runtime-rs/crates/hypervisor/src/device/driver/virtio_fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,28 @@
// SPDX-License-Identifier: Apache-2.0
//

#[derive(Copy, Clone, Debug)]
pub enum ShareFsOperation {
use anyhow::{Context, Result};
use async_trait::async_trait;

use crate::device::{hypervisor, Device, DeviceType};

#[derive(Copy, Clone, Debug, Default)]
pub enum ShareFsMountOperation {
#[default]
Mount,
Umount,
Update,
}

#[derive(Debug, Clone)]
#[derive(Debug, Default, Clone)]
pub enum ShareFsMountType {
#[default]
PASSTHROUGH,
RAFS,
}

/// ShareFsMountConfig: share fs mount config
#[derive(Debug, Clone)]
#[derive(Clone, Debug, Default)]
pub struct ShareFsMountConfig {
/// source: the passthrough fs exported dir or rafs meta file of rafs
pub source: String,
Expand All @@ -36,20 +43,19 @@ pub struct ShareFsMountConfig {
pub tag: String,

/// op: the operation to take, e.g. mount, umount or update
pub op: ShareFsOperation,
pub op: ShareFsMountOperation,

/// prefetch_list_path: path to file that contains file lists that should be prefetched by rafs
pub prefetch_list_path: Option<String>,
}

#[derive(Debug, Clone)]
pub struct ShareFsMountDevice {
gkurz marked this conversation as resolved.
Show resolved Hide resolved
pub config: ShareFsMountConfig,
}
/// ShareFsConfig: Sharefs config for virtio-fs devices and their corresponding mount configurations,
/// facilitating mount/umount/update operations.
#[derive(Clone, Debug, Default)]
pub struct ShareFsConfig {
/// host_shared_path: the upperdir of the passthrough fs exported dir or rafs meta file of rafs
pub host_shared_path: String,

/// ShareFsDeviceConfig: share fs device config
#[derive(Debug, Clone)]
pub struct ShareFsDeviceConfig {
gkurz marked this conversation as resolved.
Show resolved Hide resolved
/// fs_type: virtiofs or inline-virtiofs
pub fs_type: String,

Expand All @@ -59,9 +65,6 @@ pub struct ShareFsDeviceConfig {
/// mount_tag: a label used as a hint to the guest.
pub mount_tag: String,

/// host_path: the host filesystem path for this volume.
pub host_path: String,

/// queue_size: queue size
pub queue_size: u64,

Expand All @@ -70,9 +73,65 @@ pub struct ShareFsDeviceConfig {

/// options: virtiofs device's config options.
pub options: Vec<String>,

/// mount config for sharefs mount/umount/update
pub mount_config: Option<ShareFsMountConfig>,
gkurz marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(Debug, Clone)]
#[derive(Debug, Default, Clone)]
pub struct ShareFsDevice {
pub config: ShareFsDeviceConfig,
/// device id for sharefs device in device manager
pub device_id: String,

/// config for sharefs device
pub config: ShareFsConfig,
}

impl ShareFsDevice {
// new creates a share-fs device
pub fn new(device_id: &str, config: &ShareFsConfig) -> Self {
Self {
device_id: device_id.to_string(),
config: config.clone(),
}
}
}

#[async_trait]
impl Device for ShareFsDevice {
async fn attach(&mut self, h: &dyn hypervisor) -> Result<()> {
h.add_device(DeviceType::ShareFs(self.clone()))
.await
.context("add share-fs device.")?;

Ok(())
}

async fn detach(&mut self, _h: &dyn hypervisor) -> Result<Option<u64>> {
// no need to detach share-fs device
studychao marked this conversation as resolved.
Show resolved Hide resolved

Ok(None)
}

async fn update(&mut self, h: &dyn hypervisor) -> Result<()> {
h.update_device(DeviceType::ShareFs(self.clone()))
.await
.context("update share-fs device.")
}

async fn get_device_info(&self) -> DeviceType {
DeviceType::ShareFs(self.clone())
}

async fn increase_attach_count(&mut self) -> Result<bool> {
// share-fs devices will not be attached multiple times, Just return Ok(false)

Ok(false)
}

async fn decrease_attach_count(&mut self) -> Result<bool> {
// share-fs devices will not be detached multiple times, Just return Ok(false)

Ok(false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ impl Device for NetworkDevice {
Ok(Some(self.config.index))
}

async fn update(&mut self, _h: &dyn hypervisor) -> Result<()> {
// There's no need to do update for network device
Ok(())
}

async fn get_device_info(&self) -> DeviceType {
DeviceType::Network(self.clone())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ impl Device for HybridVsockDevice {
Ok(None)
}

async fn update(&mut self, _h: &dyn hypervisor) -> Result<()> {
// There's no need to do update for hvsock device
Ok(())
}

async fn get_device_info(&self) -> DeviceType {
DeviceType::HybridVsock(self.clone())
}
Expand Down