vmm: Add 'hotplug_size' to memory zones

In anticipation for resizing support of an individual memory zone,
this commit introduces a new option 'hotplug_size' to '--memory-zone'
parameter. This defines the amount of memory that can be added through
each specific memory zone.

Because memory zone resize is tied to virtio-mem, make sure the user
selects 'virtio-mem' hotplug method, otherwise return an error.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-09-10 12:20:22 +02:00
parent 30ff7e108f
commit c645a72c17
5 changed files with 40 additions and 5 deletions

View File

@ -112,8 +112,7 @@ _Example_
Amount of memory that can be dynamically added to the VM. Amount of memory that can be dynamically added to the VM.
Value is an unsigned integer of 64 bits. A value of 0 simply means that no Value is an unsigned integer of 64 bits. A value of 0 is invalid.
memory can be added to the VM.
_Example_ _Example_
@ -149,11 +148,12 @@ struct MemoryZoneConfig {
shared: bool, shared: bool,
hugepages: bool, hugepages: bool,
host_numa_node: Option<u32>, host_numa_node: Option<u32>,
hotplug_size: Option<u64>,
} }
``` ```
``` ```
--memory-zone <memory-zone> User defined memory zone parameters "size=<guest_memory_region_size>,file=<backing_file>,shared=on|off,hugepages=on|off,host_numa_node=<node_id>,id=<zone_identifier>" --memory-zone <memory-zone> User defined memory zone parameters "size=<guest_memory_region_size>,file=<backing_file>,shared=on|off,hugepages=on|off,host_numa_node=<node_id>,id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>"
``` ```
This parameter expects one or more occurences, allowing for a list of memory This parameter expects one or more occurences, allowing for a list of memory
@ -288,6 +288,21 @@ _Example_
--memory-zone id=mem0,size=1G,host_numa_node=0 --memory-zone id=mem0,size=1G,host_numa_node=0
``` ```
### `hotplug_size`
Amount of memory that can be dynamically added to the memory zone. Since
`virtio-mem` is the only way of resizing a memory zone, one must specify
the `hotplug_method=virtio-mem` to the `--memory` parameter.
Value is an unsigned integer of 64 bits. A value of 0 is invalid.
_Example_
```
--memory size=0,hotplug_method=virtio-mem
--memory-zone id=mem0,size=1G,hotplug_size=1G
```
## NUMA settings ## NUMA settings
`NumaConfig` or what is known as `--numa` from the CLI perspective has been `NumaConfig` or what is known as `--numa` from the CLI perspective has been

View File

@ -121,7 +121,7 @@ fn create_app<'a, 'b>(
"User defined memory zone parameters \ "User defined memory zone parameters \
\"size=<guest_memory_region_size>,file=<backing_file>,\ \"size=<guest_memory_region_size>,file=<backing_file>,\
shared=on|off,hugepages=on|off,host_numa_node=<node_id>,\ shared=on|off,hugepages=on|off,host_numa_node=<node_id>,\
id=<zone_identifier>\"", id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>\"",
) )
.takes_value(true) .takes_value(true)
.min_values(1) .min_values(1)

View File

@ -477,6 +477,9 @@ components:
host_numa_node: host_numa_node:
type: integer type: integer
format: uint32 format: uint32
hotplug_size:
type: integer
format: int64
MemoryConfig: MemoryConfig:
required: required:

View File

@ -379,6 +379,8 @@ pub struct MemoryZoneConfig {
pub hugepages: bool, pub hugepages: bool,
#[serde(default)] #[serde(default)]
pub host_numa_node: Option<u32>, pub host_numa_node: Option<u32>,
#[serde(default)]
pub hotplug_size: Option<u64>,
} }
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
@ -460,7 +462,8 @@ impl MemoryConfig {
.add("file") .add("file")
.add("shared") .add("shared")
.add("hugepages") .add("hugepages")
.add("host_numa_node"); .add("host_numa_node")
.add("hotplug_size");
parser.parse(memory_zone).map_err(Error::ParseMemoryZone)?; parser.parse(memory_zone).map_err(Error::ParseMemoryZone)?;
let id = parser.get("id").ok_or(Error::ParseMemoryZoneIdMissing)?; let id = parser.get("id").ok_or(Error::ParseMemoryZoneIdMissing)?;
@ -483,6 +486,10 @@ impl MemoryConfig {
let host_numa_node = parser let host_numa_node = parser
.convert::<u32>("host_numa_node") .convert::<u32>("host_numa_node")
.map_err(Error::ParseMemoryZone)?; .map_err(Error::ParseMemoryZone)?;
let hotplug_size = parser
.convert::<ByteSized>("hotplug_size")
.map_err(Error::ParseMemoryZone)?
.map(|v| v.0);
zones.push(MemoryZoneConfig { zones.push(MemoryZoneConfig {
id, id,
@ -491,6 +498,7 @@ impl MemoryConfig {
shared, shared,
hugepages, hugepages,
host_numa_node, host_numa_node,
hotplug_size,
}); });
} }
Some(zones) Some(zones)

View File

@ -215,6 +215,9 @@ pub enum Error {
/// Invalid size for resizing. Can be anything except 0. /// Invalid size for resizing. Can be anything except 0.
InvalidHotplugSize, InvalidHotplugSize,
/// Invalid hotplug method associated with memory zones resizing capability.
InvalidHotplugMethodWithMemoryZones,
} }
const ENABLE_FLAG: usize = 0; const ENABLE_FLAG: usize = 0;
@ -442,6 +445,7 @@ impl MemoryManager {
shared: config.shared, shared: config.shared,
hugepages: config.hugepages, hugepages: config.hugepages,
host_numa_node: None, host_numa_node: None,
hotplug_size: config.hotplug_size,
}]; }];
(config.size, zones) (config.size, zones)
@ -472,6 +476,11 @@ impl MemoryManager {
); );
return Err(Error::InvalidSharedMemoryZoneWithHostNuma); return Err(Error::InvalidSharedMemoryZoneWithHostNuma);
} }
if zone.hotplug_size.is_some() && config.hotplug_method == HotplugMethod::Acpi {
error!("Invalid to set ACPI hotplug method for memory zones");
return Err(Error::InvalidHotplugMethodWithMemoryZones);
}
} }
(total_ram_size, zones) (total_ram_size, zones)