Skip to content

Commit 749e01c

Browse files
committed
feat(virtio-pmem): add device to the VmResources
Update VmResources type with virtio-pmem configuration field to allow virtio-pmem devices be configured through config files and later through API calls. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent 8ace79e commit 749e01c

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

src/vmm/src/device_manager/pci_mngr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,8 @@ mod tests {
730730
}},
731731
"entropy": {{
732732
"rate_limiter": null
733-
}}
733+
}},
734+
"pmem": []
734735
}}"#,
735736
_block_files.last().unwrap().as_path().to_str().unwrap(),
736737
tmp_sock_file.as_path().to_str().unwrap()

src/vmm/src/device_manager/persist.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,8 @@ mod tests {
750750
}},
751751
"entropy": {{
752752
"rate_limiter": null
753-
}}
753+
}},
754+
"pmem": []
754755
}}"#,
755756
_block_files.last().unwrap().as_path().to_str().unwrap(),
756757
tmp_sock_file.as_path().to_str().unwrap()

src/vmm/src/resources.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use crate::vmm_config::machine_config::{
2828
use crate::vmm_config::metrics::{MetricsConfig, MetricsConfigError, init_metrics};
2929
use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError};
3030
use crate::vmm_config::net::*;
31+
use crate::vmm_config::pmem::{PmemBuilder, PmemConfig, PmemConfigError};
3132
use crate::vmm_config::serial::SerialConfig;
3233
use crate::vmm_config::vsock::*;
3334
use crate::vstate::memory;
@@ -62,6 +63,8 @@ pub enum ResourcesError {
6263
VsockDevice(#[from] VsockConfigError),
6364
/// Entropy device error: {0}
6465
EntropyDevice(#[from] EntropyDeviceError),
66+
/// Pmem device error: {0}
67+
PmemDevice(#[from] PmemConfigError),
6568
}
6669

6770
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
@@ -87,6 +90,8 @@ pub struct VmmConfig {
8790
network_interfaces: Vec<NetworkInterfaceConfig>,
8891
vsock: Option<VsockDeviceConfig>,
8992
entropy: Option<EntropyDeviceConfig>,
93+
#[serde(default, rename = "pmem")]
94+
pmem_devices: Vec<PmemConfig>,
9095
#[serde(skip)]
9196
serial_config: Option<SerialConfig>,
9297
}
@@ -109,6 +114,8 @@ pub struct VmResources {
109114
pub net_builder: NetBuilder,
110115
/// The entropy device builder.
111116
pub entropy: EntropyDeviceBuilder,
117+
/// The pmem devices.
118+
pub pmem: PmemBuilder,
112119
/// The optional Mmds data store.
113120
// This is initialised on demand (if ever used), so that we don't allocate it unless it's
114121
// actually used.
@@ -198,6 +205,10 @@ impl VmResources {
198205
resources.build_entropy_device(entropy_device_config)?;
199206
}
200207

208+
for pmem_config in vmm_config.pmem_devices.into_iter() {
209+
resources.build_pmem_device(pmem_config)?;
210+
}
211+
201212
if let Some(serial_cfg) = vmm_config.serial_config {
202213
resources.serial_out_path = serial_cfg.serial_out_path;
203214
}
@@ -389,6 +400,11 @@ impl VmResources {
389400
self.entropy.insert(body)
390401
}
391402

403+
/// Builds a pmem device to be attached when the VM starts.
404+
pub fn build_pmem_device(&mut self, body: PmemConfig) -> Result<(), PmemConfigError> {
405+
self.pmem.build(body)
406+
}
407+
392408
/// Setter for mmds config.
393409
pub fn set_mmds_config(
394410
&mut self,
@@ -515,6 +531,7 @@ impl From<&VmResources> for VmmConfig {
515531
network_interfaces: resources.net_builder.configs(),
516532
vsock: resources.vsock.config(),
517533
entropy: resources.entropy.config(),
534+
pmem_devices: resources.pmem.configs(),
518535
// serial_config is marked serde(skip) so that it doesnt end up in snapshots.
519536
serial_config: None,
520537
}
@@ -627,6 +644,7 @@ mod tests {
627644
boot_timer: false,
628645
mmds_size_limit: HTTP_MAX_PAYLOAD_SIZE,
629646
entropy: Default::default(),
647+
pmem: Default::default(),
630648
pci_enabled: false,
631649
serial_out_path: None,
632650
}
@@ -636,6 +654,8 @@ mod tests {
636654
fn test_from_json() {
637655
let kernel_file = TempFile::new().unwrap();
638656
let rootfs_file = TempFile::new().unwrap();
657+
let scratch_file = TempFile::new().unwrap();
658+
scratch_file.as_file().set_len(0x1000).unwrap();
639659
let default_instance_info = InstanceInfo::default();
640660

641661
// We will test different scenarios with invalid resources configuration and
@@ -1010,6 +1030,14 @@ mod tests {
10101030
"is_read_only": false
10111031
}}
10121032
],
1033+
"pmem": [
1034+
{{
1035+
"id": "pmem",
1036+
"path_on_host": "{}",
1037+
"root_device": false,
1038+
"read_only": false
1039+
}}
1040+
],
10131041
"network-interfaces": [
10141042
{{
10151043
"iface_id": "netif",
@@ -1028,6 +1056,7 @@ mod tests {
10281056
}}"#,
10291057
kernel_file.as_path().to_str().unwrap(),
10301058
rootfs_file.as_path().to_str().unwrap(),
1059+
scratch_file.as_path().to_str().unwrap(),
10311060
);
10321061
let resources = VmResources::from_json(
10331062
json.as_str(),
@@ -1640,4 +1669,20 @@ mod tests {
16401669
vm_resources.build_net_device(new_net_device_cfg).unwrap();
16411670
assert_eq!(vm_resources.net_builder.len(), 2);
16421671
}
1672+
1673+
#[test]
1674+
fn test_set_pmem_device() {
1675+
let mut vm_resources = default_vm_resources();
1676+
1677+
let tmp_file = TempFile::new().unwrap();
1678+
tmp_file.as_file().set_len(0x1000).unwrap();
1679+
let cfg = PmemConfig {
1680+
id: "pmem".to_string(),
1681+
path_on_host: tmp_file.as_path().to_str().unwrap().to_string(),
1682+
..Default::default()
1683+
};
1684+
assert_eq!(vm_resources.pmem.devices.len(), 0);
1685+
vm_resources.build_pmem_device(cfg).unwrap();
1686+
assert_eq!(vm_resources.pmem.devices.len(), 1);
1687+
}
16431688
}

src/vmm/src/rpc_interface.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::vmm_config::mmds::{MmdsConfig, MmdsConfigError};
3333
use crate::vmm_config::net::{
3434
NetworkInterfaceConfig, NetworkInterfaceError, NetworkInterfaceUpdateConfig,
3535
};
36+
use crate::vmm_config::pmem::{PmemConfig, PmemConfigError};
3637
use crate::vmm_config::serial::SerialConfig;
3738
use crate::vmm_config::snapshot::{CreateSnapshotParams, LoadSnapshotParams, SnapshotType};
3839
use crate::vmm_config::vsock::{VsockConfigError, VsockDeviceConfig};
@@ -75,6 +76,8 @@ pub enum VmmAction {
7576
/// Add a new block device or update one that already exists using the `BlockDeviceConfig` as
7677
/// input. This action can only be called before the microVM has booted.
7778
InsertBlockDevice(BlockDeviceConfig),
79+
/// Add a virtio-pmem device.
80+
InsertPmemDevice(PmemConfig),
7881
/// Add a new network interface config or update one that already exists using the
7982
/// `NetworkInterfaceConfig` as input. This action can only be called before the microVM has
8083
/// booted.
@@ -143,6 +146,8 @@ pub enum VmmActionError {
143146
DriveConfig(#[from] DriveError),
144147
/// Entropy device error: {0}
145148
EntropyDevice(#[from] EntropyDeviceError),
149+
/// Pmem device error: {0}
150+
PmemDevice(#[from] PmemConfigError),
146151
/// Internal VMM error: {0}
147152
InternalVmm(#[from] VmmError),
148153
/// Load snapshot error: {0}
@@ -432,6 +437,7 @@ impl<'a> PrebootApiController<'a> {
432437
GetVmInstanceInfo => Ok(VmmData::InstanceInformation(self.instance_info.clone())),
433438
GetVmmVersion => Ok(VmmData::VmmVersion(self.instance_info.vmm_version.clone())),
434439
InsertBlockDevice(config) => self.insert_block_device(config),
440+
InsertPmemDevice(config) => self.insert_pmem_device(config),
435441
InsertNetworkDevice(config) => self.insert_net_device(config),
436442
LoadSnapshot(config) => self
437443
.load_snapshot(&config)
@@ -489,6 +495,14 @@ impl<'a> PrebootApiController<'a> {
489495
.map_err(VmmActionError::NetworkConfig)
490496
}
491497

498+
fn insert_pmem_device(&mut self, cfg: PmemConfig) -> Result<VmmData, VmmActionError> {
499+
self.boot_path = true;
500+
self.vm_resources
501+
.build_pmem_device(cfg)
502+
.map(|()| VmmData::Empty)
503+
.map_err(VmmActionError::PmemDevice)
504+
}
505+
492506
fn set_balloon_device(&mut self, cfg: BalloonDeviceConfig) -> Result<VmmData, VmmActionError> {
493507
self.boot_path = true;
494508
self.vm_resources
@@ -687,6 +701,7 @@ impl RuntimeApiController {
687701
| ConfigureMetrics(_)
688702
| ConfigureSerial(_)
689703
| InsertBlockDevice(_)
704+
| InsertPmemDevice(_)
690705
| InsertNetworkDevice(_)
691706
| LoadSnapshot(_)
692707
| PutCpuConfiguration(_)
@@ -1272,5 +1287,11 @@ mod tests {
12721287
check_unsupported(runtime_request(VmmAction::SetEntropyDevice(
12731288
EntropyDeviceConfig::default(),
12741289
)));
1290+
check_unsupported(runtime_request(VmmAction::InsertPmemDevice(PmemConfig {
1291+
id: String::new(),
1292+
path_on_host: String::new(),
1293+
root_device: false,
1294+
read_only: false,
1295+
})));
12751296
}
12761297
}

0 commit comments

Comments
 (0)