Skip to main content

disk_backend_resources/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Disk resources, for use with [`vm_resource`].
5
6#![forbid(unsafe_code)]
7
8pub mod layer;
9
10use mesh::Cell;
11use mesh::MeshPayload;
12use std::time::Duration;
13use vm_resource::IntoResource;
14use vm_resource::Resource;
15use vm_resource::ResourceId;
16use vm_resource::kind::DiskHandleKind;
17use vm_resource::kind::DiskLayerHandleKind;
18
19// Define config types here so that you don't have to pull in the individual
20// crates just to describe the configuration.
21
22/// File-backed disk handle.
23#[derive(MeshPayload)]
24pub struct FileDiskHandle(pub std::fs::File);
25
26impl ResourceId<DiskHandleKind> for FileDiskHandle {
27    const ID: &'static str = "file";
28}
29
30/// Block-device-backed disk handle (Linux).
31///
32/// Uses `io_uring` for async I/O.
33#[derive(MeshPayload)]
34pub struct BlockDeviceDiskHandle {
35    /// The file handle for the block device or regular file.
36    pub file: std::fs::File,
37}
38
39impl ResourceId<DiskHandleKind> for BlockDeviceDiskHandle {
40    const ID: &'static str = "block";
41}
42
43/// Disk handle for a disk that emulates persistent reservation support.
44#[derive(MeshPayload)]
45pub struct DiskWithReservationsHandle(pub Resource<DiskHandleKind>);
46
47impl ResourceId<DiskHandleKind> for DiskWithReservationsHandle {
48    const ID: &'static str = "prwrap";
49}
50
51/// Disk handle for a delay disk.
52#[derive(MeshPayload)]
53pub struct DelayDiskHandle {
54    /// The underlying disk resource.
55    pub disk: Resource<DiskHandleKind>,
56    /// The delay to add to each I/O operation.
57    pub delay: Cell<Duration>,
58}
59
60impl ResourceId<DiskHandleKind> for DelayDiskHandle {
61    const ID: &'static str = "delay";
62}
63
64/// Disk handle for a fixed VHD1 disk.
65#[derive(MeshPayload)]
66pub struct FixedVhd1DiskHandle(pub std::fs::File);
67
68impl ResourceId<DiskHandleKind> for FixedVhd1DiskHandle {
69    const ID: &'static str = "fixed_vhd1";
70}
71
72/// Disk configuration for a striped disk.
73#[derive(MeshPayload)]
74pub struct StripedDiskHandle {
75    /// The underlying disks for the stripes.
76    pub devices: Vec<Resource<DiskHandleKind>>,
77    /// The size of each stripe.
78    pub chunk_size_in_bytes: Option<u32>,
79    /// The number of sectors to show for the disk.
80    pub logic_sector_count: Option<u64>,
81}
82
83impl ResourceId<DiskHandleKind> for StripedDiskHandle {
84    const ID: &'static str = "striped";
85}
86
87/// Configuration for a disk that is automatically formatted (if it is not
88/// already formatted) while being resolved.
89// DEVNOTE: this disk type supports a Azure-specific feature in Microsoft's
90// closed-source OpenHCL. Due to the NTFS formatting library being used, the
91// backing disk type and resolver are currently not able to be open-sourced.
92//
93// Unfortunately, this feature needs to "leak" into the open-source OpenVMM
94// codebase, due to tight coupling in the code of Vtl2Settings.
95#[derive(MeshPayload)]
96pub struct AutoFormattedDiskHandle {
97    /// The disk resource.
98    pub disk: Resource<DiskHandleKind>,
99    /// The GUID to check for.
100    pub guid: [u8; 16],
101}
102
103impl ResourceId<DiskHandleKind> for AutoFormattedDiskHandle {
104    const ID: &'static str = "ntfsfmt";
105}
106
107// blob
108
109/// Handle for a read-only disk backed by a blob served over HTTP.
110#[derive(MeshPayload)]
111pub struct BlobDiskHandle {
112    /// The URL to the disk.
113    pub url: String,
114    /// The format of the blob.
115    pub format: BlobDiskFormat,
116}
117
118impl ResourceId<DiskHandleKind> for BlobDiskHandle {
119    const ID: &'static str = "blob";
120}
121
122/// The format of a disk blob.
123#[derive(MeshPayload)]
124pub enum BlobDiskFormat {
125    /// A flat blob, with no additional metadata.
126    Flat,
127    /// A fixed VHD1, with a VHD footer specifying disk metadata.
128    FixedVhd1,
129}
130
131/// Handle for a disk that is backed by one or more layers.
132#[derive(MeshPayload)]
133pub struct LayeredDiskHandle {
134    /// The layers that make up the disk. The first layer is the top-most layer.
135    pub layers: Vec<DiskLayerDescription>,
136}
137
138impl LayeredDiskHandle {
139    /// Create a new layered disk handle with a single layer.
140    pub fn single_layer(layer: impl IntoResource<DiskLayerHandleKind>) -> Self {
141        Self {
142            layers: vec![layer.into_resource().into()],
143        }
144    }
145}
146
147impl ResourceId<DiskHandleKind> for LayeredDiskHandle {
148    const ID: &'static str = "layered";
149}
150
151/// Description of a disk layer.
152#[derive(MeshPayload)]
153pub struct DiskLayerDescription {
154    /// The layer resource.
155    pub layer: Resource<DiskLayerHandleKind>,
156    /// If true, reads that miss this layer are written back to this layer.
157    pub read_cache: bool,
158    /// If true, writes are written both to this layer and the next one.
159    pub write_through: bool,
160}
161
162impl From<Resource<DiskLayerHandleKind>> for DiskLayerDescription {
163    fn from(layer: Resource<DiskLayerHandleKind>) -> Self {
164        Self {
165            layer,
166            read_cache: false,
167            write_through: false,
168        }
169    }
170}