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/// Handle for a flat VMDK disk.
73#[derive(MeshPayload)]
74pub struct FlatVmdkDiskHandle {
75    /// Open host files referenced by the descriptor.
76    pub files: Vec<std::fs::File>,
77    /// Ordered virtual-disk extents.
78    pub extents: Vec<FlatVmdkExtent>,
79}
80
81impl ResourceId<DiskHandleKind> for FlatVmdkDiskHandle {
82    const ID: &'static str = "vmdk_flat";
83}
84
85/// One flat VMDK extent.
86#[derive(MeshPayload)]
87pub struct FlatVmdkExtent {
88    /// Index into [`FlatVmdkDiskHandle::files`].
89    pub file_index: u32,
90    /// Access mode declared by the descriptor.
91    pub access: VmdkExtentAccess,
92    /// Number of 512-byte sectors in this extent.
93    pub sector_count: u64,
94    /// First 512-byte sector read from the source file.
95    pub source_start_sector: u64,
96}
97
98/// Access mode declared for a VMDK extent.
99#[derive(MeshPayload)]
100pub enum VmdkExtentAccess {
101    /// The descriptor permits reads and writes.
102    ReadWrite,
103    /// The descriptor permits only reads.
104    ReadOnly,
105}
106
107/// Disk configuration for a striped disk.
108#[derive(MeshPayload)]
109pub struct StripedDiskHandle {
110    /// The underlying disks for the stripes.
111    pub devices: Vec<Resource<DiskHandleKind>>,
112    /// The size of each stripe.
113    pub chunk_size_in_bytes: Option<u32>,
114    /// The number of sectors to show for the disk.
115    pub logic_sector_count: Option<u64>,
116}
117
118impl ResourceId<DiskHandleKind> for StripedDiskHandle {
119    const ID: &'static str = "striped";
120}
121
122/// Configuration for a disk that is automatically formatted (if it is not
123/// already formatted) while being resolved.
124// DEVNOTE: this disk type supports a Azure-specific feature in Microsoft's
125// closed-source OpenHCL. Due to the NTFS formatting library being used, the
126// backing disk type and resolver are currently not able to be open-sourced.
127//
128// Unfortunately, this feature needs to "leak" into the open-source OpenVMM
129// codebase, due to tight coupling in the code of Vtl2Settings.
130#[derive(MeshPayload)]
131pub struct AutoFormattedDiskHandle {
132    /// The disk resource.
133    pub disk: Resource<DiskHandleKind>,
134    /// The GUID to check for.
135    pub guid: [u8; 16],
136}
137
138impl ResourceId<DiskHandleKind> for AutoFormattedDiskHandle {
139    const ID: &'static str = "ntfsfmt";
140}
141
142// blob
143
144/// Handle for a read-only disk backed by a blob served over HTTP.
145#[derive(MeshPayload)]
146pub struct BlobDiskHandle {
147    /// The URL to the disk.
148    pub url: String,
149    /// The format of the blob.
150    pub format: BlobDiskFormat,
151}
152
153impl ResourceId<DiskHandleKind> for BlobDiskHandle {
154    const ID: &'static str = "blob";
155}
156
157/// The format of a disk blob.
158#[derive(MeshPayload)]
159pub enum BlobDiskFormat {
160    /// A flat blob, with no additional metadata.
161    Flat,
162    /// A fixed VHD1, with a VHD footer specifying disk metadata.
163    FixedVhd1,
164}
165
166/// Handle for a disk that is backed by one or more layers.
167#[derive(MeshPayload)]
168pub struct LayeredDiskHandle {
169    /// The layers that make up the disk. The first layer is the top-most layer.
170    pub layers: Vec<DiskLayerDescription>,
171}
172
173impl LayeredDiskHandle {
174    /// Create a new layered disk handle with a single layer.
175    pub fn single_layer(layer: impl IntoResource<DiskLayerHandleKind>) -> Self {
176        Self {
177            layers: vec![layer.into_resource().into()],
178        }
179    }
180}
181
182impl ResourceId<DiskHandleKind> for LayeredDiskHandle {
183    const ID: &'static str = "layered";
184}
185
186/// Description of a disk layer.
187#[derive(MeshPayload)]
188pub struct DiskLayerDescription {
189    /// The layer resource.
190    pub layer: Resource<DiskLayerHandleKind>,
191    /// If true, reads that miss this layer are written back to this layer.
192    pub read_cache: bool,
193    /// If true, writes are written both to this layer and the next one.
194    pub write_through: bool,
195}
196
197impl From<Resource<DiskLayerHandleKind>> for DiskLayerDescription {
198    fn from(layer: Resource<DiskLayerHandleKind>) -> Self {
199        Self {
200            layer,
201            read_cache: false,
202            write_through: false,
203        }
204    }
205}