From 33a1e37c35ecf6d782ad6dd6aa4805718d3ad8e4 Mon Sep 17 00:00:00 2001 From: Hui Zhu Date: Mon, 10 Aug 2020 18:22:55 +0800 Subject: [PATCH] virtio-devices: mem: Allow for an initial size This commit gives the possibility to create a virtio-mem device with some memory already plugged into it. This is preliminary work to be able to reboot a VM with the virtio-mem region being already resized. Signed-off-by: Hui Zhu Signed-off-by: Sebastien Boeuf --- virtio-devices/src/mem.rs | 81 ++++++++++++++++++++++++--------------- vmm/src/device_manager.rs | 1 + 2 files changed, 51 insertions(+), 31 deletions(-) diff --git a/virtio-devices/src/mem.rs b/virtio-devices/src/mem.rs index b6d22a9ae..c7f6bf226 100644 --- a/virtio-devices/src/mem.rs +++ b/virtio-devices/src/mem.rs @@ -185,6 +185,36 @@ struct VirtioMemConfig { // Safe because it only has data and has no implicit padding. unsafe impl ByteValued for VirtioMemConfig {} +fn virtio_mem_config_resize(config: &mut VirtioMemConfig, size: u64) -> result::Result<(), Error> { + if config.requested_size == size { + return Err(Error::ResizeInval(format!( + "Virtio-mem resize {} is same with current config.requested_size", + size + ))); + } else if size > config.region_size { + let region_size = config.region_size; + return Err(Error::ResizeInval(format!( + "Virtio-mem resize {} is bigger than config.region_size {}", + size, region_size + ))); + } else if size % (config.block_size as u64) != 0 { + let block_size = config.block_size; + return Err(Error::ResizeInval(format!( + "Virtio-mem resize {} is not aligned with config.block_size {}", + size, block_size + ))); + } + + config.requested_size = size; + let tmp_size = cmp::min( + config.region_size, + config.requested_size + VIRTIO_MEM_USABLE_EXTENT, + ); + config.usable_region_size = cmp::max(config.usable_region_size, tmp_size); + + Ok(()) +} + struct Request { req: VirtioMemReq, status_addr: GuestAddress, @@ -622,37 +652,16 @@ impl EpollHelperHandler for MemEpollHandler { let size = self.resize.get_size(); let mut config = self.config.lock().unwrap(); let mut signal_error = false; - let r = if config.requested_size == size { - Err(Error::ResizeInval(format!( - "Virtio-mem resize {} is same with current config.requested_size", - size - ))) - } else if size > config.region_size { - let region_size = config.region_size; - Err(Error::ResizeInval(format!( - "Virtio-mem resize {} is bigger than config.region_size {}", - size, region_size - ))) - } else if size % (config.block_size as u64) != 0 { - let block_size = config.block_size; - Err(Error::ResizeInval(format!( - "Virtio-mem resize {} is not aligned with config.block_size {}", - size, block_size - ))) - } else { - config.requested_size = size; - let tmp_size = cmp::min( - config.region_size, - config.requested_size + VIRTIO_MEM_USABLE_EXTENT, - ); - config.usable_region_size = cmp::max(config.usable_region_size, tmp_size); - if let Err(e) = self.signal(&VirtioInterruptType::Config) { - signal_error = true; - error!("Error signalling config: {:?}", e); - Err(Error::ResizeTriggerFail(e)) - } else { - Ok(()) - } + let mut r = virtio_mem_config_resize(&mut config, size); + r = match r { + Err(e) => Err(e), + _ => match self.signal(&VirtioInterruptType::Config) { + Err(e) => { + signal_error = true; + Err(Error::ResizeTriggerFail(e)) + } + _ => Ok(()), + }, }; if let Err(e) = self.resize.send(r) { error!("Sending \"resize\" reponse: {:?}", e); @@ -702,6 +711,7 @@ impl Mem { resize: Resize, seccomp_action: SeccompAction, numa_node_id: Option, + initial_size: u64, ) -> io::Result { let region_len = region.len(); @@ -726,6 +736,15 @@ impl Mem { config.requested_size + VIRTIO_MEM_USABLE_EXTENT, ); + if initial_size != 0 { + virtio_mem_config_resize(&mut config, initial_size).map_err(|e| { + io::Error::new( + io::ErrorKind::Other, + format!("Virtio-mem resize {} got {:?}", initial_size, e), + ) + })?; + } + if let Some(node_id) = numa_node_id { avail_features |= 1u64 << VIRTIO_MEM_F_ACPI_PXM; config.node_id = node_id; diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 992436d60..d2267191d 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -2451,6 +2451,7 @@ impl DeviceManager { .map_err(DeviceManagerError::TryCloneVirtioMemResize)?, self.seccomp_action.clone(), node_id, + 0, ) .map_err(DeviceManagerError::CreateVirtioMem)?, ));