Skip to content

Commit

Permalink
disk_backend: add new layered disk (#404)
Browse files Browse the repository at this point in the history
Add a new disk type `LayeredDisk` that is composed of multiple layers,
each of which can contribute an arbitrary subset of the sectors of the
composed disk.

This is useful for modeling differencing VHDs, the RAM diff disk, and
the upcoming sqlite-backed disk. It can be used to providing disk
snapshots and read and write caches.

In this PR, only the RAM disk and the full disk layers are defined.
  • Loading branch information
jstarks authored Nov 29, 2024
1 parent a177fe6 commit b3940de
Show file tree
Hide file tree
Showing 30 changed files with 1,625 additions and 400 deletions.
22 changes: 18 additions & 4 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,21 @@ dependencies = [
"vmgs_broker",
]

[[package]]
name = "disk_layered"
version = "0.0.0"
dependencies = [
"async-trait",
"disk_backend",
"disk_backend_resources",
"futures",
"guestmem",
"inspect",
"scsi_buffers",
"thiserror 2.0.0",
"vm_resource",
]

[[package]]
name = "disk_nvme"
version = "0.0.0"
Expand Down Expand Up @@ -1250,15 +1265,16 @@ name = "disk_ramdisk"
version = "0.0.0"
dependencies = [
"anyhow",
"async-trait",
"disk_backend",
"disk_backend_resources",
"disk_layered",
"event-listener",
"guestmem",
"inspect",
"pal_async",
"parking_lot",
"scsi_buffers",
"test_with_tracing",
"thiserror 2.0.0",
"tracing",
"vm_resource",
Expand Down Expand Up @@ -1992,7 +2008,6 @@ dependencies = [
"chipset_arc_mutex_device",
"chipset_device",
"chipset_device_fuzz",
"disk_backend",
"disk_ramdisk",
"guestmem",
"ide",
Expand Down Expand Up @@ -4197,7 +4212,6 @@ version = "0.0.0"
dependencies = [
"anyhow",
"chipset_device",
"disk_backend",
"disk_ramdisk",
"event-listener",
"futures",
Expand Down Expand Up @@ -4550,6 +4564,7 @@ dependencies = [
"disk_blob",
"disk_crypt",
"disk_file",
"disk_layered",
"disk_prwrap",
"disk_ramdisk",
"disk_vhd1",
Expand Down Expand Up @@ -5983,7 +5998,6 @@ dependencies = [
"anyhow",
"async-trait",
"criterion",
"disk_backend",
"disk_ramdisk",
"event-listener",
"fast_select",
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ disk_crypt = { path = "vm/devices/storage/disk_crypt" }
disk_crypt_resources = { path = "vm/devices/storage/disk_crypt_resources" }
disk_file = { path = "vm/devices/storage/disk_file" }
disk_get_vmgs = { path = "vm/devices/storage/disk_get_vmgs" }
disk_layered = { path = "vm/devices/storage/disk_layered" }
disk_nvme = { path = "vm/devices/storage/disk_nvme" }
disk_ramdisk = { path = "vm/devices/storage/disk_ramdisk" }
disk_striped = { path = "vm/devices/storage/disk_striped" }
Expand Down
27 changes: 20 additions & 7 deletions openvmm/openvmm_entry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use cli_args::EndpointConfigCli;
use cli_args::NicConfigCli;
use cli_args::SerialConfigCli;
use cli_args::UefiConsoleModeCli;
use disk_backend_resources::layer::DiskLayerHandle;
use disk_backend_resources::layer::RamDiskLayerHandle;
use floppy_resources::FloppyDiskConfig;
use framebuffer::FramebufferAccess;
use framebuffer::FRAMEBUFFER_SIZE;
Expand Down Expand Up @@ -843,9 +845,9 @@ fn vm_config_from_command_line(
let vmgs_disk = if let Some(disk) = &opt.get_vmgs {
disk_open(disk, false).context("failed to open GET vmgs disk")?
} else {
disk_backend_resources::RamDiskHandle {
len: vmgs_format::VMGS_DEFAULT_CAPACITY,
}
disk_backend_resources::LayeredDiskHandle::single_layer(RamDiskLayerHandle {
len: Some(vmgs_format::VMGS_DEFAULT_CAPACITY),
})
.into_resource()
};
vmbus_devices.extend([
Expand Down Expand Up @@ -1415,7 +1417,11 @@ impl NicConfig {

fn disk_open(disk_cli: &DiskCliKind, read_only: bool) -> anyhow::Result<Resource<DiskHandleKind>> {
let disk_type = match disk_cli {
&DiskCliKind::Memory(len) => Resource::new(disk_backend_resources::RamDiskHandle { len }),
&DiskCliKind::Memory(len) => {
Resource::new(disk_backend_resources::LayeredDiskHandle::single_layer(
RamDiskLayerHandle { len: Some(len) },
))
}
DiskCliKind::File(path) => open_disk_type(path, read_only)
.with_context(|| format!("failed to open {}", path.display()))?,
DiskCliKind::Blob { kind, url } => Resource::new(disk_backend_resources::BlobDiskHandle {
Expand All @@ -1426,8 +1432,13 @@ fn disk_open(disk_cli: &DiskCliKind, read_only: bool) -> anyhow::Result<Resource
},
}),
DiskCliKind::MemoryDiff(inner) => {
Resource::new(disk_backend_resources::RamDiffDiskHandle {
lower: disk_open(inner, true)?,
Resource::new(disk_backend_resources::LayeredDiskHandle {
layers: vec![
RamDiskLayerHandle { len: None }.into_resource().into(),
DiskLayerHandle(disk_open(inner, true)?)
.into_resource()
.into(),
],
})
}
DiskCliKind::PersistentReservationsWrapper(inner) => Resource::new(
Expand Down Expand Up @@ -2367,7 +2378,9 @@ async fn run_control(driver: &DefaultDriver, mesh: &VmmMesh, opt: Options) -> an
.with_context(|| format!("failed to open {}", path.display()))?
}
Some(size) => {
Resource::new(disk_backend_resources::RamDiskHandle { len: size })
Resource::new(disk_backend_resources::LayeredDiskHandle::single_layer(
RamDiskLayerHandle { len: Some(size) },
))
}
};

Expand Down
1 change: 1 addition & 0 deletions openvmm/openvmm_resources/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ serial_socket.workspace = true
disk_blob = { workspace = true, optional = true }
disk_crypt = { workspace = true, optional = true }
disk_file.workspace = true
disk_layered.workspace = true
disk_prwrap.workspace = true
disk_ramdisk.workspace = true
disk_vhd1.workspace = true
Expand Down
1 change: 1 addition & 0 deletions openvmm/openvmm_resources/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ vm_resource::register_static_resolvers! {
net_dio::resolver::DioResolver,

// Disks
disk_layered::resolver::LayeredDiskResolver,
#[cfg(feature = "disk_crypt")]
disk_crypt::resolver::DiskCryptResolver,
disk_ramdisk::resolver::RamDiskResolver,
Expand Down
36 changes: 27 additions & 9 deletions petri/src/vm/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ use crate::BOOT_NVME_NSID;
use crate::SCSI_INSTANCE;
use crate::SIZE_1_GB;
use anyhow::Context;
use disk_backend_resources::RamDiffDiskHandle;
use disk_backend_resources::layer::DiskLayerHandle;
use disk_backend_resources::layer::RamDiskLayerHandle;
use disk_backend_resources::LayeredDiskHandle;
use framebuffer::Framebuffer;
use framebuffer::FramebufferAccess;
use framebuffer::FRAMEBUFFER_SIZE;
Expand Down Expand Up @@ -753,7 +755,13 @@ impl PetriVmConfigSetupCore<'_> {
PcatGuest::Vhd(_) => GuestMedia::Disk {
read_only: false,
disk_parameters: None,
disk_type: (RamDiffDiskHandle { lower: inner_disk }).into_resource(),
disk_type: LayeredDiskHandle {
layers: vec![
RamDiskLayerHandle { len: None }.into_resource().into(),
DiskLayerHandle(inner_disk).into_resource().into(),
],
}
.into_resource(),
},
PcatGuest::Iso(_) => GuestMedia::Dvd(
SimpleScsiDvdHandle {
Expand Down Expand Up @@ -793,8 +801,13 @@ impl PetriVmConfigSetupCore<'_> {
device: SimpleScsiDiskHandle {
read_only: false,
parameters: Default::default(),
disk: RamDiffDiskHandle {
lower: open_disk_type(&path, true)?,
disk: LayeredDiskHandle {
layers: vec![
RamDiskLayerHandle { len: None }.into_resource().into(),
DiskLayerHandle(open_disk_type(&path, true)?)
.into_resource()
.into(),
],
}
.into_resource(),
}
Expand All @@ -820,8 +833,13 @@ impl PetriVmConfigSetupCore<'_> {
msix_count: 64,
namespaces: vec![NamespaceDefinition {
nsid: BOOT_NVME_NSID,
disk: RamDiffDiskHandle {
lower: open_disk_type(&path, true)?,
disk: LayeredDiskHandle {
layers: vec![
RamDiskLayerHandle { len: None }.into_resource().into(),
DiskLayerHandle(open_disk_type(&path, true)?)
.into_resource()
.into(),
],
}
.into_resource(),
read_only: false,
Expand Down Expand Up @@ -928,9 +946,9 @@ impl PetriVmConfigSetupCore<'_> {
vmbus_redirection: false,
vtl2_settings: None, // Will be added at startup to allow tests to modify
vmgs_disk: Some(
disk_backend_resources::RamDiskHandle {
len: vmgs_format::VMGS_DEFAULT_CAPACITY,
}
LayeredDiskHandle::single_layer(RamDiskLayerHandle {
len: Some(vmgs_format::VMGS_DEFAULT_CAPACITY),
})
.into_resource(),
),
framebuffer: framebuffer.then(|| SharedFramebufferHandle.into_resource()),
Expand Down
6 changes: 1 addition & 5 deletions vm/devices/get/guest_emulation_device/src/test_utilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::GedChannel;
use crate::GuestConfig;
use crate::GuestEmulationDevice;
use crate::GuestFirmwareConfig;
use disk_backend::Disk;
use get_protocol::test_utilities::TEST_VMGS_CAPACITY;
use get_protocol::HostNotifications;
use get_protocol::HostRequests;
Expand Down Expand Up @@ -264,10 +263,7 @@ pub fn create_host_channel(
None,
recv,
None,
Some(
Disk::new(disk_ramdisk::RamDisk::new(TEST_VMGS_CAPACITY as u64, false).unwrap())
.unwrap(),
),
Some(disk_ramdisk::ram_disk(TEST_VMGS_CAPACITY as u64, false).unwrap()),
);

if let Some(ged_responses) = ged_responses {
Expand Down
7 changes: 1 addition & 6 deletions vm/devices/storage/disk_backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@
//! (such as the VMGS file system).
//!
//! `Disk`s are backed by a [`DiskIo`] implementation. Specific disk
//! backends should be in their own crates. The exceptions that prove the rule
//! is [`ZeroDisk`][], which is small enough to be in this crate and serve as an
//! example.
//!
//! [`ZeroDisk`]: crate::zerodisk::ZeroDisk
//! backends should be in their own crates.
#![forbid(unsafe_code)]
#![warn(missing_docs)]

pub mod pr;
pub mod resolve;
pub mod sync_wrapper;
pub mod zerodisk;

use guestmem::AccessError;
use inspect::Inspect;
Expand Down
110 changes: 0 additions & 110 deletions vm/devices/storage/disk_backend/src/zerodisk.rs

This file was deleted.

Loading

0 comments on commit b3940de

Please sign in to comment.