mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
vmm: Add 'hotplugged_size' to memory parameters
Add the new option 'hotplugged_size' to both --memory-zone and --memory parameters so that we can let the user specify a certain amount of memory being plugged at boot. This is also part of making sure we can store the virtio-mem size over a reboot of the VM. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
33a1e37c35
commit
4e1b78e1ff
@ -17,6 +17,7 @@ struct MemoryConfig {
|
|||||||
hugepages: bool,
|
hugepages: bool,
|
||||||
hotplug_method: HotplugMethod,
|
hotplug_method: HotplugMethod,
|
||||||
hotplug_size: Option<u64>,
|
hotplug_size: Option<u64>,
|
||||||
|
hotplugged_size: Option<u64>,
|
||||||
balloon: bool,
|
balloon: bool,
|
||||||
balloon_size: u64,
|
balloon_size: u64,
|
||||||
zones: Option<Vec<MemoryZoneConfig>>,
|
zones: Option<Vec<MemoryZoneConfig>>,
|
||||||
@ -24,7 +25,7 @@ struct MemoryConfig {
|
|||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
--memory <memory> Memory parameters "size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,hotplug_method=acpi|virtio-mem,hotplug_size=<hotpluggable_memory_size>,balloon=on|off"
|
--memory <memory> Memory parameters "size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,hotplug_method=acpi|virtio-mem,hotplug_size=<hotpluggable_memory_size>,hotplugged_size=<hotplugged_memory_size>,balloon=on|off"
|
||||||
```
|
```
|
||||||
|
|
||||||
### `size`
|
### `size`
|
||||||
@ -120,6 +121,27 @@ _Example_
|
|||||||
--memory size=1G,hotplug_size=1G
|
--memory size=1G,hotplug_size=1G
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `hotplugged_size`
|
||||||
|
|
||||||
|
Amount of memory that will be dynamically added to the VM at boot. This option
|
||||||
|
allows for starting a VM with a certain amount of memory that can be reduced
|
||||||
|
during runtime.
|
||||||
|
|
||||||
|
This is only valid when the `hotplug_method` is `virtio-mem` as it does not
|
||||||
|
make sense for the `acpi` use case. When using ACPI, the memory can't be
|
||||||
|
resized after it has been extended.
|
||||||
|
|
||||||
|
This option is only valid when `hotplug_size` is specified, and its value can't
|
||||||
|
exceed the value of `hotplug_size`.
|
||||||
|
|
||||||
|
Value is an unsigned integer of 64 bits. A value of 0 is invalid.
|
||||||
|
|
||||||
|
_Example_
|
||||||
|
|
||||||
|
```
|
||||||
|
--memory size=1G,hotplug_method=virtio-mem,hotplug_size=1G,hotplugged_size=512M
|
||||||
|
```
|
||||||
|
|
||||||
### `balloon`
|
### `balloon`
|
||||||
|
|
||||||
Specifies if the `virtio-balloon` device must be activated. This creates a
|
Specifies if the `virtio-balloon` device must be activated. This creates a
|
||||||
@ -149,11 +171,12 @@ struct MemoryZoneConfig {
|
|||||||
hugepages: bool,
|
hugepages: bool,
|
||||||
host_numa_node: Option<u32>,
|
host_numa_node: Option<u32>,
|
||||||
hotplug_size: Option<u64>,
|
hotplug_size: Option<u64>,
|
||||||
|
hotplugged_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>,hotplug_size=<hotpluggable_memory_size>"
|
--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>,hotplugged_size=<hotplugged_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
|
||||||
@ -303,6 +326,28 @@ _Example_
|
|||||||
--memory-zone id=mem0,size=1G,hotplug_size=1G
|
--memory-zone id=mem0,size=1G,hotplug_size=1G
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `hotplugged_size`
|
||||||
|
|
||||||
|
Amount of memory that will be dynamically added to a memory zone at VM's boot.
|
||||||
|
This option allows for starting a VM with a certain amount of memory that can
|
||||||
|
be reduced during runtime.
|
||||||
|
|
||||||
|
This is only valid when the `hotplug_method` is `virtio-mem` as it does not
|
||||||
|
make sense for the `acpi` use case. When using ACPI, the memory can't be
|
||||||
|
resized after it has been extended.
|
||||||
|
|
||||||
|
This option is only valid when `hotplug_size` is specified, and its value can't
|
||||||
|
exceed the value of `hotplug_size`.
|
||||||
|
|
||||||
|
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,hotplugged_size=512M
|
||||||
|
```
|
||||||
|
|
||||||
## 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
|
||||||
|
@ -109,7 +109,8 @@ fn create_app<'a, 'b>(
|
|||||||
"Memory parameters \
|
"Memory parameters \
|
||||||
\"size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,\
|
\"size=<guest_memory_size>,mergeable=on|off,shared=on|off,hugepages=on|off,\
|
||||||
hotplug_method=acpi|virtio-mem,\
|
hotplug_method=acpi|virtio-mem,\
|
||||||
hotplug_size=<hotpluggable_memory_size>\"",
|
hotplug_size=<hotpluggable_memory_size>,\
|
||||||
|
hotplugged_size=<hotplugged_memory_size>\"",
|
||||||
)
|
)
|
||||||
.default_value(&default_memory)
|
.default_value(&default_memory)
|
||||||
.group("vm-config"),
|
.group("vm-config"),
|
||||||
@ -121,7 +122,8 @@ 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>,hotplug_size=<hotpluggable_memory_size>\"",
|
id=<zone_identifier>,hotplug_size=<hotpluggable_memory_size>,\
|
||||||
|
hotplugged_size=<hotplugged_memory_size>\"",
|
||||||
)
|
)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.min_values(1)
|
.min_values(1)
|
||||||
@ -539,6 +541,7 @@ mod unit_tests {
|
|||||||
mergeable: false,
|
mergeable: false,
|
||||||
hotplug_method: HotplugMethod::Acpi,
|
hotplug_method: HotplugMethod::Acpi,
|
||||||
hotplug_size: None,
|
hotplug_size: None,
|
||||||
|
hotplugged_size: None,
|
||||||
shared: false,
|
shared: false,
|
||||||
hugepages: false,
|
hugepages: false,
|
||||||
balloon: false,
|
balloon: false,
|
||||||
|
@ -496,6 +496,9 @@ components:
|
|||||||
hotplug_size:
|
hotplug_size:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
hotplugged_size:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
|
|
||||||
MemoryConfig:
|
MemoryConfig:
|
||||||
required:
|
required:
|
||||||
@ -509,6 +512,9 @@ components:
|
|||||||
hotplug_size:
|
hotplug_size:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
|
hotplugged_size:
|
||||||
|
type: integer
|
||||||
|
format: int64
|
||||||
mergeable:
|
mergeable:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
@ -381,6 +381,8 @@ pub struct MemoryZoneConfig {
|
|||||||
pub host_numa_node: Option<u32>,
|
pub host_numa_node: Option<u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub hotplug_size: Option<u64>,
|
pub hotplug_size: Option<u64>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub hotplugged_size: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||||
@ -393,6 +395,8 @@ pub struct MemoryConfig {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub hotplug_size: Option<u64>,
|
pub hotplug_size: Option<u64>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub hotplugged_size: Option<u64>,
|
||||||
|
#[serde(default)]
|
||||||
pub shared: bool,
|
pub shared: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub hugepages: bool,
|
pub hugepages: bool,
|
||||||
@ -413,6 +417,7 @@ impl MemoryConfig {
|
|||||||
.add("mergeable")
|
.add("mergeable")
|
||||||
.add("hotplug_method")
|
.add("hotplug_method")
|
||||||
.add("hotplug_size")
|
.add("hotplug_size")
|
||||||
|
.add("hotplugged_size")
|
||||||
.add("shared")
|
.add("shared")
|
||||||
.add("hugepages")
|
.add("hugepages")
|
||||||
.add("balloon");
|
.add("balloon");
|
||||||
@ -436,6 +441,10 @@ impl MemoryConfig {
|
|||||||
.convert::<ByteSized>("hotplug_size")
|
.convert::<ByteSized>("hotplug_size")
|
||||||
.map_err(Error::ParseMemory)?
|
.map_err(Error::ParseMemory)?
|
||||||
.map(|v| v.0);
|
.map(|v| v.0);
|
||||||
|
let hotplugged_size = parser
|
||||||
|
.convert::<ByteSized>("hotplugged_size")
|
||||||
|
.map_err(Error::ParseMemory)?
|
||||||
|
.map(|v| v.0);
|
||||||
let shared = parser
|
let shared = parser
|
||||||
.convert::<Toggle>("shared")
|
.convert::<Toggle>("shared")
|
||||||
.map_err(Error::ParseMemory)?
|
.map_err(Error::ParseMemory)?
|
||||||
@ -463,7 +472,8 @@ impl MemoryConfig {
|
|||||||
.add("shared")
|
.add("shared")
|
||||||
.add("hugepages")
|
.add("hugepages")
|
||||||
.add("host_numa_node")
|
.add("host_numa_node")
|
||||||
.add("hotplug_size");
|
.add("hotplug_size")
|
||||||
|
.add("hotplugged_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)?;
|
||||||
@ -490,6 +500,10 @@ impl MemoryConfig {
|
|||||||
.convert::<ByteSized>("hotplug_size")
|
.convert::<ByteSized>("hotplug_size")
|
||||||
.map_err(Error::ParseMemoryZone)?
|
.map_err(Error::ParseMemoryZone)?
|
||||||
.map(|v| v.0);
|
.map(|v| v.0);
|
||||||
|
let hotplugged_size = parser
|
||||||
|
.convert::<ByteSized>("hotplugged_size")
|
||||||
|
.map_err(Error::ParseMemoryZone)?
|
||||||
|
.map(|v| v.0);
|
||||||
|
|
||||||
zones.push(MemoryZoneConfig {
|
zones.push(MemoryZoneConfig {
|
||||||
id,
|
id,
|
||||||
@ -499,6 +513,7 @@ impl MemoryConfig {
|
|||||||
hugepages,
|
hugepages,
|
||||||
host_numa_node,
|
host_numa_node,
|
||||||
hotplug_size,
|
hotplug_size,
|
||||||
|
hotplugged_size,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Some(zones)
|
Some(zones)
|
||||||
@ -511,6 +526,7 @@ impl MemoryConfig {
|
|||||||
mergeable,
|
mergeable,
|
||||||
hotplug_method,
|
hotplug_method,
|
||||||
hotplug_size,
|
hotplug_size,
|
||||||
|
hotplugged_size,
|
||||||
shared,
|
shared,
|
||||||
hugepages,
|
hugepages,
|
||||||
balloon,
|
balloon,
|
||||||
@ -527,6 +543,7 @@ impl Default for MemoryConfig {
|
|||||||
mergeable: false,
|
mergeable: false,
|
||||||
hotplug_method: HotplugMethod::Acpi,
|
hotplug_method: HotplugMethod::Acpi,
|
||||||
hotplug_size: None,
|
hotplug_size: None,
|
||||||
|
hotplugged_size: None,
|
||||||
shared: false,
|
shared: false,
|
||||||
hugepages: false,
|
hugepages: false,
|
||||||
balloon: false,
|
balloon: false,
|
||||||
@ -2118,6 +2135,7 @@ mod tests {
|
|||||||
mergeable: false,
|
mergeable: false,
|
||||||
hotplug_method: HotplugMethod::Acpi,
|
hotplug_method: HotplugMethod::Acpi,
|
||||||
hotplug_size: None,
|
hotplug_size: None,
|
||||||
|
hotplugged_size: None,
|
||||||
shared: false,
|
shared: false,
|
||||||
hugepages: false,
|
hugepages: false,
|
||||||
balloon: false,
|
balloon: false,
|
||||||
|
@ -440,6 +440,32 @@ impl MemoryManager {
|
|||||||
return Err(Error::InvalidMemoryParameters);
|
return Err(Error::InvalidMemoryParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(hotplugged_size) = config.hotplugged_size {
|
||||||
|
if let Some(hotplug_size) = config.hotplug_size {
|
||||||
|
if hotplugged_size > hotplug_size {
|
||||||
|
error!(
|
||||||
|
"'hotplugged_size' {} can't be bigger than \
|
||||||
|
'hotplug_size' {}",
|
||||||
|
hotplugged_size, hotplug_size,
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidMemoryParameters);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Invalid to define 'hotplugged_size' when there is\
|
||||||
|
no 'hotplug_size'"
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidMemoryParameters);
|
||||||
|
}
|
||||||
|
if config.hotplug_method == HotplugMethod::Acpi {
|
||||||
|
error!(
|
||||||
|
"Invalid to define 'hotplugged_size' with hotplug \
|
||||||
|
method 'acpi'"
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidMemoryParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a single zone from the global memory config. This lets
|
// Create a single zone from the global memory config. This lets
|
||||||
// us reuse the codepath for user defined memory zones.
|
// us reuse the codepath for user defined memory zones.
|
||||||
let zones = vec![MemoryZoneConfig {
|
let zones = vec![MemoryZoneConfig {
|
||||||
@ -450,6 +476,7 @@ impl MemoryManager {
|
|||||||
hugepages: config.hugepages,
|
hugepages: config.hugepages,
|
||||||
host_numa_node: None,
|
host_numa_node: None,
|
||||||
hotplug_size: config.hotplug_size,
|
hotplug_size: config.hotplug_size,
|
||||||
|
hotplugged_size: config.hotplugged_size,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
(config.size, zones)
|
(config.size, zones)
|
||||||
@ -485,6 +512,32 @@ impl MemoryManager {
|
|||||||
error!("Invalid to set ACPI hotplug method for memory zones");
|
error!("Invalid to set ACPI hotplug method for memory zones");
|
||||||
return Err(Error::InvalidHotplugMethodWithMemoryZones);
|
return Err(Error::InvalidHotplugMethodWithMemoryZones);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(hotplugged_size) = zone.hotplugged_size {
|
||||||
|
if let Some(hotplug_size) = zone.hotplug_size {
|
||||||
|
if hotplugged_size > hotplug_size {
|
||||||
|
error!(
|
||||||
|
"'hotplugged_size' {} can't be bigger than \
|
||||||
|
'hotplug_size' {}",
|
||||||
|
hotplugged_size, hotplug_size,
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidMemoryParameters);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!(
|
||||||
|
"Invalid to define 'hotplugged_size' when there is\
|
||||||
|
no 'hotplug_size' for a memory zone"
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidMemoryParameters);
|
||||||
|
}
|
||||||
|
if config.hotplug_method == HotplugMethod::Acpi {
|
||||||
|
error!(
|
||||||
|
"Invalid to define 'hotplugged_size' with hotplug \
|
||||||
|
method 'acpi'"
|
||||||
|
);
|
||||||
|
return Err(Error::InvalidMemoryParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(total_ram_size, zones)
|
(total_ram_size, zones)
|
||||||
|
Loading…
Reference in New Issue
Block a user