Skip to content

Commit ba37c03

Browse files
Manciukicbchalios
authored andcommitted
fix(vmm): fix patch of pci devices
The vmm was only checking the mmio device manager for finding the device to update. Use the generic device manager instead. Also update unit tests that expect a specific string. Signed-off-by: Riccardo Mancini <[email protected]> Signed-off-by: Babis Chalios <[email protected]>
1 parent 045bf67 commit ba37c03

File tree

3 files changed

+43
-10
lines changed

3 files changed

+43
-10
lines changed

src/vmm/src/device_manager/mod.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,17 @@ pub enum AttachDeviceError {
8181
PciTransport(#[from] PciManagerError),
8282
}
8383

84+
#[derive(Debug, thiserror::Error, displaydoc::Display)]
85+
/// Error while searching for a VirtIO device
86+
pub enum FindDeviceError {
87+
/// Device type is invalid
88+
InvalidDeviceType,
89+
/// Device not found
90+
DeviceNotFound,
91+
/// Internal Device error: {0}
92+
InternalDeviceError(String),
93+
}
94+
8495
#[derive(Debug)]
8596
/// A manager of all peripheral devices of Firecracker
8697
pub struct DeviceManager {
@@ -342,6 +353,30 @@ impl DeviceManager {
342353
)
343354
}
344355
}
356+
357+
/// Run fn `f()` for the virtio device matching `virtio_type` and `id`.
358+
pub fn with_virtio_device_with_id<T, F>(
359+
&self,
360+
virtio_type: u32,
361+
id: &str,
362+
f: F,
363+
) -> Result<(), FindDeviceError>
364+
where
365+
T: VirtioDevice + 'static + Debug,
366+
F: FnOnce(&mut T) -> Result<(), String>,
367+
{
368+
if let Some(device) = self.get_virtio_device(virtio_type, id) {
369+
let mut dev = device.lock().expect("Poisoned lock");
370+
f(dev
371+
.as_mut_any()
372+
.downcast_mut::<T>()
373+
.ok_or(FindDeviceError::InvalidDeviceType)?)
374+
.map_err(FindDeviceError::InternalDeviceError)?;
375+
} else {
376+
return Err(FindDeviceError::DeviceNotFound);
377+
}
378+
Ok(())
379+
}
345380
}
346381

347382
#[derive(Debug, Default, Clone, Serialize, Deserialize)]

src/vmm/src/lib.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ pub enum VmmError {
252252
VmmObserverTeardown(vmm_sys_util::errno::Error),
253253
/// VMGenID error: {0}
254254
VMGenID(#[from] VmGenIdError),
255+
/// Failed perform action on device: {0}
256+
FindDeviceError(#[from] device_manager::FindDeviceError),
255257
}
256258

257259
/// Shorthand type for KVM dirty page bitmap.
@@ -535,13 +537,12 @@ impl Vmm {
535537
path_on_host: String,
536538
) -> Result<(), VmmError> {
537539
self.device_manager
538-
.mmio_devices
539540
.with_virtio_device_with_id(TYPE_BLOCK, drive_id, |block: &mut Block| {
540541
block
541542
.update_disk_image(path_on_host)
542543
.map_err(|err| err.to_string())
543544
})
544-
.map_err(VmmError::MmioDeviceManager)
545+
.map_err(VmmError::FindDeviceError)
545546
}
546547

547548
/// Updates the rate limiter parameters for block device with `drive_id` id.
@@ -552,23 +553,21 @@ impl Vmm {
552553
rl_ops: BucketUpdate,
553554
) -> Result<(), VmmError> {
554555
self.device_manager
555-
.mmio_devices
556556
.with_virtio_device_with_id(TYPE_BLOCK, drive_id, |block: &mut Block| {
557557
block
558558
.update_rate_limiter(rl_bytes, rl_ops)
559559
.map_err(|err| err.to_string())
560560
})
561-
.map_err(VmmError::MmioDeviceManager)
561+
.map_err(VmmError::FindDeviceError)
562562
}
563563

564564
/// Updates the rate limiter parameters for block device with `drive_id` id.
565565
pub fn update_vhost_user_block_config(&mut self, drive_id: &str) -> Result<(), VmmError> {
566566
self.device_manager
567-
.mmio_devices
568567
.with_virtio_device_with_id(TYPE_BLOCK, drive_id, |block: &mut Block| {
569568
block.update_config().map_err(|err| err.to_string())
570569
})
571-
.map_err(VmmError::MmioDeviceManager)
570+
.map_err(VmmError::FindDeviceError)
572571
}
573572

574573
/// Updates the rate limiter parameters for net device with `net_id` id.
@@ -581,12 +580,11 @@ impl Vmm {
581580
tx_ops: BucketUpdate,
582581
) -> Result<(), VmmError> {
583582
self.device_manager
584-
.mmio_devices
585583
.with_virtio_device_with_id(TYPE_NET, net_id, |net: &mut Net| {
586584
net.patch_rate_limiters(rx_bytes, rx_ops, tx_bytes, tx_ops);
587585
Ok(())
588586
})
589-
.map_err(VmmError::MmioDeviceManager)
587+
.map_err(VmmError::FindDeviceError)
590588
}
591589

592590
/// Returns a reference to the balloon device if present.

tests/integration_tests/functional/test_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ def test_send_ctrl_alt_del(uvm_plain_any):
772772
def _drive_patch(test_microvm, io_engine):
773773
"""Exercise drive patch test scenarios."""
774774
# Patches without mandatory fields for virtio block are not allowed.
775-
expected_msg = "Unable to patch the block device: MMIO Device manager error: Running method expected different backend. Please verify the request arguments"
775+
expected_msg = "Running method expected different backend."
776776
with pytest.raises(RuntimeError, match=expected_msg):
777777
test_microvm.api.drive.patch(drive_id="scratch")
778778

@@ -814,7 +814,7 @@ def _drive_patch(test_microvm, io_engine):
814814
)
815815

816816
# Updates to `path_on_host` with an invalid path are not allowed.
817-
expected_msg = f"Unable to patch the block device: MMIO Device manager error: Virtio backend error: Error manipulating the backing file: No such file or directory (os error 2) {drive_path} Please verify the request arguments"
817+
expected_msg = f"Error manipulating the backing file: No such file or directory (os error 2) {drive_path}"
818818
with pytest.raises(RuntimeError, match=re.escape(expected_msg)):
819819
test_microvm.api.drive.patch(drive_id="scratch", path_on_host=drive_path)
820820

0 commit comments

Comments
 (0)