mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 11:05:46 +00:00
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 <teawater@antfin.com> Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
8b5202aa5a
commit
33a1e37c35
@ -185,6 +185,36 @@ struct VirtioMemConfig {
|
|||||||
// Safe because it only has data and has no implicit padding.
|
// Safe because it only has data and has no implicit padding.
|
||||||
unsafe impl ByteValued for VirtioMemConfig {}
|
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 {
|
struct Request {
|
||||||
req: VirtioMemReq,
|
req: VirtioMemReq,
|
||||||
status_addr: GuestAddress,
|
status_addr: GuestAddress,
|
||||||
@ -622,37 +652,16 @@ impl EpollHelperHandler for MemEpollHandler {
|
|||||||
let size = self.resize.get_size();
|
let size = self.resize.get_size();
|
||||||
let mut config = self.config.lock().unwrap();
|
let mut config = self.config.lock().unwrap();
|
||||||
let mut signal_error = false;
|
let mut signal_error = false;
|
||||||
let r = if config.requested_size == size {
|
let mut r = virtio_mem_config_resize(&mut config, size);
|
||||||
Err(Error::ResizeInval(format!(
|
r = match r {
|
||||||
"Virtio-mem resize {} is same with current config.requested_size",
|
Err(e) => Err(e),
|
||||||
size
|
_ => match self.signal(&VirtioInterruptType::Config) {
|
||||||
)))
|
Err(e) => {
|
||||||
} else if size > config.region_size {
|
signal_error = true;
|
||||||
let region_size = config.region_size;
|
Err(Error::ResizeTriggerFail(e))
|
||||||
Err(Error::ResizeInval(format!(
|
}
|
||||||
"Virtio-mem resize {} is bigger than config.region_size {}",
|
_ => Ok(()),
|
||||||
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(())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Err(e) = self.resize.send(r) {
|
if let Err(e) = self.resize.send(r) {
|
||||||
error!("Sending \"resize\" reponse: {:?}", e);
|
error!("Sending \"resize\" reponse: {:?}", e);
|
||||||
@ -702,6 +711,7 @@ impl Mem {
|
|||||||
resize: Resize,
|
resize: Resize,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
numa_node_id: Option<u16>,
|
numa_node_id: Option<u16>,
|
||||||
|
initial_size: u64,
|
||||||
) -> io::Result<Mem> {
|
) -> io::Result<Mem> {
|
||||||
let region_len = region.len();
|
let region_len = region.len();
|
||||||
|
|
||||||
@ -726,6 +736,15 @@ impl Mem {
|
|||||||
config.requested_size + VIRTIO_MEM_USABLE_EXTENT,
|
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 {
|
if let Some(node_id) = numa_node_id {
|
||||||
avail_features |= 1u64 << VIRTIO_MEM_F_ACPI_PXM;
|
avail_features |= 1u64 << VIRTIO_MEM_F_ACPI_PXM;
|
||||||
config.node_id = node_id;
|
config.node_id = node_id;
|
||||||
|
@ -2451,6 +2451,7 @@ impl DeviceManager {
|
|||||||
.map_err(DeviceManagerError::TryCloneVirtioMemResize)?,
|
.map_err(DeviceManagerError::TryCloneVirtioMemResize)?,
|
||||||
self.seccomp_action.clone(),
|
self.seccomp_action.clone(),
|
||||||
node_id,
|
node_id,
|
||||||
|
0,
|
||||||
)
|
)
|
||||||
.map_err(DeviceManagerError::CreateVirtioMem)?,
|
.map_err(DeviceManagerError::CreateVirtioMem)?,
|
||||||
));
|
));
|
||||||
|
Loading…
Reference in New Issue
Block a user