mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
vmm: disk resize infrastructure
Add basic infrastructure so resize events are propagated to the underlying disk implementation. On-behalf-of: SAP thomas.prescher@sap.com Signed-off-by: Thomas Prescher <thomas.prescher@cyberus-technology.de>
This commit is contained in:
committed by
Rob Bradford
parent
8e52bf251b
commit
37d71fa038
@@ -18,6 +18,12 @@ pub enum DiskFileError {
|
||||
/// Failed creating a new AsyncIo.
|
||||
#[error("Failed creating a new AsyncIo")]
|
||||
NewAsyncIo(#[source] std::io::Error),
|
||||
/// Unsupported operation.
|
||||
#[error("Unsupported operation")]
|
||||
Unsupported,
|
||||
/// Resize failed
|
||||
#[error("Resize failed")]
|
||||
ResizeError(#[source] std::io::Error),
|
||||
}
|
||||
|
||||
pub type DiskFileResult<T> = std::result::Result<T, DiskFileError>;
|
||||
@@ -68,6 +74,10 @@ pub trait DiskFile: Send {
|
||||
fn topology(&mut self) -> DiskTopology {
|
||||
DiskTopology::default()
|
||||
}
|
||||
fn resize(&mut self, _size: u64) -> DiskFileResult<()> {
|
||||
Err(DiskFileError::Unsupported)
|
||||
}
|
||||
|
||||
/// Returns the file descriptor of the underlying disk image file.
|
||||
///
|
||||
/// The file descriptor is supposed to be used for `fcntl()` calls but no
|
||||
|
||||
@@ -108,6 +108,10 @@ impl RequestHandler for StubApiRequestHandler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_resize_disk(&mut self, _: String, _: u64) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn vm_coredump(&mut self, _: &str) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::sync::{Arc, Barrier};
|
||||
use std::{io, result};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use block::async_io::{AsyncIo, AsyncIoError, DiskFile};
|
||||
use block::async_io::{AsyncIo, AsyncIoError, DiskFile, DiskFileError};
|
||||
use block::fcntl::{LockError, LockGranularity, LockType, get_lock_state};
|
||||
use block::{
|
||||
ExecuteAsync, ExecuteError, Request, RequestType, VirtioBlockConfig, build_serial, fcntl,
|
||||
@@ -95,6 +95,16 @@ pub enum Error {
|
||||
/// The path of the disk image.
|
||||
path: PathBuf,
|
||||
},
|
||||
#[error("Disk image size is not a multiple of {}", SECTOR_SIZE)]
|
||||
InvalidSize,
|
||||
#[error("Failed to pause vcpus")]
|
||||
PauseVcpus(#[source] MigratableError),
|
||||
#[error("Failed to resume vcpus")]
|
||||
ResumeVcpus(#[source] MigratableError),
|
||||
#[error("Failed signal config interrupt")]
|
||||
ConfigChange(#[source] io::Error),
|
||||
#[error("Disk resize failed")]
|
||||
DiskResize(#[source] DiskFileError),
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
@@ -870,6 +880,34 @@ impl Block {
|
||||
self.writeback.store(writeback, Ordering::Release);
|
||||
}
|
||||
|
||||
pub fn resize(&mut self, new_size: u64) -> Result<()> {
|
||||
if !new_size.is_multiple_of(SECTOR_SIZE) {
|
||||
return Err(Error::InvalidSize);
|
||||
}
|
||||
|
||||
self.disk_image
|
||||
.resize(new_size)
|
||||
.map_err(Error::DiskResize)?;
|
||||
|
||||
let nsectors = new_size / SECTOR_SIZE;
|
||||
|
||||
self.common.pause().map_err(Error::PauseVcpus)?;
|
||||
|
||||
self.disk_nsectors.store(nsectors, Ordering::SeqCst);
|
||||
self.config.capacity = nsectors;
|
||||
self.state().disk_nsectors = nsectors;
|
||||
|
||||
self.common.resume().map_err(Error::ResumeVcpus)?;
|
||||
|
||||
if let Some(interrupt_cb) = self.common.interrupt_cb.as_ref() {
|
||||
interrupt_cb
|
||||
.trigger(VirtioInterruptType::Config)
|
||||
.map_err(Error::ConfigChange)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(fuzzing)]
|
||||
pub fn wait_for_epoll_threads(&mut self) {
|
||||
self.common.wait_for_epoll_threads();
|
||||
|
||||
@@ -315,6 +315,8 @@ pub trait RequestHandler {
|
||||
|
||||
fn vm_resize_zone(&mut self, id: String, desired_ram: u64) -> Result<(), VmError>;
|
||||
|
||||
fn vm_resize_disk(&mut self, id: String, desired_size: u64) -> Result<(), VmError>;
|
||||
|
||||
fn vm_add_device(&mut self, device_cfg: DeviceConfig) -> Result<Option<Vec<u8>>, VmError>;
|
||||
|
||||
fn vm_add_user_device(
|
||||
|
||||
@@ -670,6 +670,10 @@ pub enum DeviceManagerError {
|
||||
/// Error adding fw_cfg to bus.
|
||||
#[error("Error adding fw_cfg to bus")]
|
||||
ErrorAddingFwCfgToBus(#[source] vm_device::BusError),
|
||||
|
||||
/// Disk resizing failed.
|
||||
#[error("Disk resize error")]
|
||||
DiskResize(#[source] virtio_devices::block::Error),
|
||||
}
|
||||
|
||||
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
||||
@@ -4901,6 +4905,18 @@ impl DeviceManager {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn resize_disk(&mut self, device_id: &str, new_size: u64) -> DeviceManagerResult<()> {
|
||||
for dev in &self.block_devices {
|
||||
let mut disk = dev.lock().unwrap();
|
||||
if disk.id() == device_id {
|
||||
return disk
|
||||
.resize(new_size)
|
||||
.map_err(DeviceManagerError::DiskResize);
|
||||
}
|
||||
}
|
||||
Err(DeviceManagerError::UnknownDeviceId(device_id.to_string()))
|
||||
}
|
||||
|
||||
pub fn device_tree(&self) -> Arc<Mutex<DeviceTree>> {
|
||||
self.device_tree.clone()
|
||||
}
|
||||
|
||||
@@ -1962,6 +1962,16 @@ impl RequestHandler for Vmm {
|
||||
}
|
||||
}
|
||||
|
||||
fn vm_resize_disk(&mut self, id: String, desired_size: u64) -> result::Result<(), VmError> {
|
||||
self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
|
||||
|
||||
if let Some(ref mut vm) = self.vm {
|
||||
return vm.resize_disk(&id, desired_size);
|
||||
}
|
||||
|
||||
Err(VmError::ResizeDisk)
|
||||
}
|
||||
|
||||
fn vm_resize_zone(&mut self, id: String, desired_ram: u64) -> result::Result<(), VmError> {
|
||||
self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
|
||||
|
||||
|
||||
@@ -246,6 +246,9 @@ pub enum Error {
|
||||
#[error("Failed resizing a memory zone")]
|
||||
ResizeZone,
|
||||
|
||||
#[error("Failed resizing a disk image")]
|
||||
ResizeDisk,
|
||||
|
||||
#[error("Cannot activate virtio devices")]
|
||||
ActivateVirtioDevices(#[source] DeviceManagerError),
|
||||
|
||||
@@ -1706,6 +1709,16 @@ impl Vm {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resize_disk(&mut self, id: &str, desired_size: u64) -> Result<()> {
|
||||
self.device_manager
|
||||
.lock()
|
||||
.unwrap()
|
||||
.resize_disk(id, desired_size)
|
||||
.map_err(Error::DeviceManager)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resize_zone(&mut self, id: &str, desired_memory: u64) -> Result<()> {
|
||||
let memory_config = &mut self.config.lock().unwrap().memory;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user