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/// Disk handle for a disk that emulates persistent reservation support.
31#[derive(MeshPayload)]
32pub struct DiskWithReservationsHandle(pub Resource<DiskHandleKind>);
33
34impl ResourceId<DiskHandleKind> for DiskWithReservationsHandle {
35    const ID: &'static str = "prwrap";
36}
37
38/// Disk handle for a delay disk.
39#[derive(MeshPayload)]
40pub struct DelayDiskHandle {
41    /// The underlying disk resource.
42    pub disk: Resource<DiskHandleKind>,
43    /// The delay to add to each I/O operation.
44    pub delay: Cell<Duration>,
45}
46
47impl ResourceId<DiskHandleKind> for DelayDiskHandle {
48    const ID: &'static str = "delay";
49}
50
51/// Disk handle for a fixed VHD1 disk.
52#[derive(MeshPayload)]
53pub struct FixedVhd1DiskHandle(pub std::fs::File);
54
55impl ResourceId<DiskHandleKind> for FixedVhd1DiskHandle {
56    const ID: &'static str = "fixed_vhd1";
57}
58
59/// Disk configuration for a striped disk.
60#[derive(MeshPayload)]
61pub struct StripedDiskHandle {
62    /// The underlying disks for the stripes.
63    pub devices: Vec<Resource<DiskHandleKind>>,
64    /// The size of each stripe.
65    pub chunk_size_in_bytes: Option<u32>,
66    /// The number of sectors to show for the disk.
67    pub logic_sector_count: Option<u64>,
68}
69
70impl ResourceId<DiskHandleKind> for StripedDiskHandle {
71    const ID: &'static str = "striped";
72}
73
74/// Configuration for a disk that is automatically formatted (if it is not
75/// already formatted) while being resolved.
76// DEVNOTE: this disk type supports a Azure-specific feature in Microsoft's
77// closed-source OpenHCL. Due to the NTFS formatting library being used, the
78// backing disk type and resolver are currently not able to be open-sourced.
79//
80// Unfortunately, this feature needs to "leak" into the open-source OpenVMM
81// codebase, due to tight coupling in the code of Vtl2Settings.
82#[derive(MeshPayload)]
83pub struct AutoFormattedDiskHandle {
84    /// The disk resource.
85    pub disk: Resource<DiskHandleKind>,
86    /// The GUID to check for.
87    pub guid: [u8; 16],
88}
89
90impl ResourceId<DiskHandleKind> for AutoFormattedDiskHandle {
91    const ID: &'static str = "ntfsfmt";
92}
93
94// blob
95
96/// Handle for a read-only disk backed by a blob served over HTTP.
97#[derive(MeshPayload)]
98pub struct BlobDiskHandle {
99    /// The URL to the disk.
100    pub url: String,
101    /// The format of the blob.
102    pub format: BlobDiskFormat,
103}
104
105impl ResourceId<DiskHandleKind> for BlobDiskHandle {
106    const ID: &'static str = "blob";
107}
108
109/// The format of a disk blob.
110#[derive(MeshPayload)]
111pub enum BlobDiskFormat {
112    /// A flat blob, with no additional metadata.
113    Flat,
114    /// A fixed VHD1, with a VHD footer specifying disk metadata.
115    FixedVhd1,
116}
117
118/// Handle for a disk that is backed by one or more layers.
119#[derive(MeshPayload)]
120pub struct LayeredDiskHandle {
121    /// The layers that make up the disk. The first layer is the top-most layer.
122    pub layers: Vec<DiskLayerDescription>,
123}
124
125impl LayeredDiskHandle {
126    /// Create a new layered disk handle with a single layer.
127    pub fn single_layer(layer: impl IntoResource<DiskLayerHandleKind>) -> Self {
128        Self {
129            layers: vec![layer.into_resource().into()],
130        }
131    }
132}
133
134impl ResourceId<DiskHandleKind> for LayeredDiskHandle {
135    const ID: &'static str = "layered";
136}
137
138/// Description of a disk layer.
139#[derive(MeshPayload)]
140pub struct DiskLayerDescription {
141    /// The layer resource.
142    pub layer: Resource<DiskLayerHandleKind>,
143    /// If true, reads that miss this layer are written back to this layer.
144    pub read_cache: bool,
145    /// If true, writes are written both to this layer and the next one.
146    pub write_through: bool,
147}
148
149impl From<Resource<DiskLayerHandleKind>> for DiskLayerDescription {
150    fn from(layer: Resource<DiskLayerHandleKind>) -> Self {
151        Self {
152            layer,
153            read_cache: false,
154            write_through: false,
155        }
156    }
157}