vmm: Improve handling of shared memory backing

As huge pages are always MAP_SHARED then where the shared memory would
be checked (for vhost-user and local migration) we can also check
instead for huge pages.

The checking is also extended to cover the memory zones based
configuration as well.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2022-10-31 13:39:11 +00:00
parent 99d9a3d299
commit f4495de143
2 changed files with 31 additions and 9 deletions

View File

@ -180,7 +180,10 @@ impl fmt::Display for ValidationError {
CpusMaxLowerThanBoot => write!(f, "Max CPUs lower than boot CPUs"),
DiskSocketAndPath => write!(f, "Disk path and vhost socket both provided"),
VhostUserRequiresSharedMemory => {
write!(f, "Using vhost-user requires using shared memory")
write!(
f,
"Using vhost-user requires using shared memory or huge pages"
)
}
VhostUserMissingSocket => write!(f, "No socket provided when using vhost-user"),
IommuUnsupported => write!(f, "Using an IOMMU without PCI support is unsupported"),
@ -216,7 +219,10 @@ impl fmt::Display for ValidationError {
write!(f, "Number of vCPUs is insufficient for number of queues")
}
UserDevicesRequireSharedMemory => {
write!(f, "Using user devices requires using shared memory")
write!(
f,
"Using user devices requires using shared memory or huge pages"
)
}
MemoryZoneReused(s, u1, u2) => {
write!(
@ -1756,6 +1762,23 @@ impl VmConfig {
Ok(())
}
pub fn backed_by_shared_memory(&self) -> bool {
if self.memory.shared || self.memory.hugepages {
return true;
}
if self.memory.size == 0 {
for zone in self.memory.zones.as_ref().unwrap() {
if !zone.shared && !zone.hugepages {
return false;
}
}
true
} else {
false
}
}
// Also enables virtio-iommu if the config needs it
// Returns the list of unique identifiers provided through the
// configuration.
@ -1800,7 +1823,7 @@ impl VmConfig {
if disk.vhost_socket.as_ref().and(disk.path.as_ref()).is_some() {
return Err(ValidationError::DiskSocketAndPath);
}
if disk.vhost_user && !self.memory.shared {
if disk.vhost_user && !self.backed_by_shared_memory() {
return Err(ValidationError::VhostUserRequiresSharedMemory);
}
if disk.vhost_user && disk.vhost_socket.is_none() {
@ -1815,7 +1838,7 @@ impl VmConfig {
if let Some(nets) = &self.net {
for net in nets {
if net.vhost_user && !self.memory.shared {
if net.vhost_user && !self.backed_by_shared_memory() {
return Err(ValidationError::VhostUserRequiresSharedMemory);
}
net.validate(self)?;
@ -1826,7 +1849,7 @@ impl VmConfig {
}
if let Some(fses) = &self.fs {
if !fses.is_empty() && !self.memory.shared {
if !fses.is_empty() && !self.backed_by_shared_memory() {
return Err(ValidationError::VhostUserRequiresSharedMemory);
}
for fs in fses {
@ -1881,7 +1904,7 @@ impl VmConfig {
}
if let Some(user_devices) = &self.user_devices {
if !user_devices.is_empty() && !self.memory.shared {
if !user_devices.is_empty() && !self.backed_by_shared_memory() {
return Err(ValidationError::UserDevicesRequireSharedMemory);
}

View File

@ -1606,12 +1606,11 @@ impl Vmm {
.unwrap()
.lock()
.unwrap()
.memory
.shared
.backed_by_shared_memory()
&& send_data_migration.local
{
return Err(MigratableError::MigrateSend(anyhow!(
"Local migration requires shared memory enabled"
"Local migration requires shared memory or hugepages enabled"
)));
}