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:
Sebastien Boeuf
2020-09-14 20:23:45 +02:00
parent 33a1e37c35
commit 4e1b78e1ff
5 changed files with 130 additions and 5 deletions

View File

@@ -496,6 +496,9 @@ components:
hotplug_size:
type: integer
format: int64
hotplugged_size:
type: integer
format: int64
MemoryConfig:
required:
@@ -509,6 +512,9 @@ components:
hotplug_size:
type: integer
format: int64
hotplugged_size:
type: integer
format: int64
mergeable:
type: boolean
default: false

View File

@@ -381,6 +381,8 @@ pub struct MemoryZoneConfig {
pub host_numa_node: Option<u32>,
#[serde(default)]
pub hotplug_size: Option<u64>,
#[serde(default)]
pub hotplugged_size: Option<u64>,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
@@ -393,6 +395,8 @@ pub struct MemoryConfig {
#[serde(default)]
pub hotplug_size: Option<u64>,
#[serde(default)]
pub hotplugged_size: Option<u64>,
#[serde(default)]
pub shared: bool,
#[serde(default)]
pub hugepages: bool,
@@ -413,6 +417,7 @@ impl MemoryConfig {
.add("mergeable")
.add("hotplug_method")
.add("hotplug_size")
.add("hotplugged_size")
.add("shared")
.add("hugepages")
.add("balloon");
@@ -436,6 +441,10 @@ impl MemoryConfig {
.convert::<ByteSized>("hotplug_size")
.map_err(Error::ParseMemory)?
.map(|v| v.0);
let hotplugged_size = parser
.convert::<ByteSized>("hotplugged_size")
.map_err(Error::ParseMemory)?
.map(|v| v.0);
let shared = parser
.convert::<Toggle>("shared")
.map_err(Error::ParseMemory)?
@@ -463,7 +472,8 @@ impl MemoryConfig {
.add("shared")
.add("hugepages")
.add("host_numa_node")
.add("hotplug_size");
.add("hotplug_size")
.add("hotplugged_size");
parser.parse(memory_zone).map_err(Error::ParseMemoryZone)?;
let id = parser.get("id").ok_or(Error::ParseMemoryZoneIdMissing)?;
@@ -490,6 +500,10 @@ impl MemoryConfig {
.convert::<ByteSized>("hotplug_size")
.map_err(Error::ParseMemoryZone)?
.map(|v| v.0);
let hotplugged_size = parser
.convert::<ByteSized>("hotplugged_size")
.map_err(Error::ParseMemoryZone)?
.map(|v| v.0);
zones.push(MemoryZoneConfig {
id,
@@ -499,6 +513,7 @@ impl MemoryConfig {
hugepages,
host_numa_node,
hotplug_size,
hotplugged_size,
});
}
Some(zones)
@@ -511,6 +526,7 @@ impl MemoryConfig {
mergeable,
hotplug_method,
hotplug_size,
hotplugged_size,
shared,
hugepages,
balloon,
@@ -527,6 +543,7 @@ impl Default for MemoryConfig {
mergeable: false,
hotplug_method: HotplugMethod::Acpi,
hotplug_size: None,
hotplugged_size: None,
shared: false,
hugepages: false,
balloon: false,
@@ -2118,6 +2135,7 @@ mod tests {
mergeable: false,
hotplug_method: HotplugMethod::Acpi,
hotplug_size: None,
hotplugged_size: None,
shared: false,
hugepages: false,
balloon: false,

View File

@@ -440,6 +440,32 @@ impl MemoryManager {
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
// us reuse the codepath for user defined memory zones.
let zones = vec![MemoryZoneConfig {
@@ -450,6 +476,7 @@ impl MemoryManager {
hugepages: config.hugepages,
host_numa_node: None,
hotplug_size: config.hotplug_size,
hotplugged_size: config.hotplugged_size,
}];
(config.size, zones)
@@ -485,6 +512,32 @@ impl MemoryManager {
error!("Invalid to set ACPI hotplug method for memory zones");
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)