mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-23 08:21:15 +00:00
vmm: memory_manager: Avoid MAP_PRIVATE CoW with VFIO for hugepages too
We can't use MAP_ANONYMOUS and still have huge pages so MAP_SHARED is effectively required when using huge pages. Unfortunately it is not as simple as always forcing MAP_SHARED if hugepages is on as this might be inappropriate in the backing file case hence why there is additional complexity of assigning to mmap_flags on each case and the MAP_SHARED is only turned on for the anonymous file huge page case as well as anonymous shared file case. See: #4805 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
df7c728399
commit
99d9a3d299
@ -1299,30 +1299,36 @@ impl MemoryManager {
|
|||||||
host_numa_node: Option<u32>,
|
host_numa_node: Option<u32>,
|
||||||
existing_memory_file: Option<File>,
|
existing_memory_file: Option<File>,
|
||||||
) -> Result<Arc<GuestRegionMmap>, Error> {
|
) -> Result<Arc<GuestRegionMmap>, Error> {
|
||||||
|
let mut mmap_flags = libc::MAP_NORESERVE;
|
||||||
|
|
||||||
|
// The duplication of mmap_flags ORing here is unfortunate but it also makes
|
||||||
|
// the complexity of the handling clear.
|
||||||
let fo = if let Some(f) = existing_memory_file {
|
let fo = if let Some(f) = existing_memory_file {
|
||||||
|
// It must be MAP_SHARED as we wouldn't already have an FD
|
||||||
|
mmap_flags |= libc::MAP_SHARED;
|
||||||
Some(FileOffset::new(f, file_offset))
|
Some(FileOffset::new(f, file_offset))
|
||||||
} else if let Some(backing_file) = backing_file {
|
} else if let Some(backing_file) = backing_file {
|
||||||
|
if shared {
|
||||||
|
mmap_flags |= libc::MAP_SHARED;
|
||||||
|
} else {
|
||||||
|
mmap_flags |= libc::MAP_PRIVATE;
|
||||||
|
}
|
||||||
Some(Self::open_backing_file(backing_file, file_offset, size)?)
|
Some(Self::open_backing_file(backing_file, file_offset, size)?)
|
||||||
} else if shared || hugepages {
|
} else if shared || hugepages {
|
||||||
|
// For hugepages we must also MAP_SHARED otherwise we will trigger #4805
|
||||||
|
// because the MAP_PRIVATE will trigger CoW against the backing file with
|
||||||
|
// the VFIO pinning
|
||||||
|
mmap_flags |= libc::MAP_SHARED;
|
||||||
Some(Self::create_anonymous_file(size, hugepages, hugepage_size)?)
|
Some(Self::create_anonymous_file(size, hugepages, hugepage_size)?)
|
||||||
} else {
|
} else {
|
||||||
|
mmap_flags |= libc::MAP_PRIVATE | libc::MAP_ANONYMOUS;
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mmap_flags = libc::MAP_NORESERVE
|
|
||||||
| if shared {
|
|
||||||
libc::MAP_SHARED
|
|
||||||
} else {
|
|
||||||
libc::MAP_PRIVATE
|
|
||||||
};
|
|
||||||
if prefault {
|
if prefault {
|
||||||
mmap_flags |= libc::MAP_POPULATE;
|
mmap_flags |= libc::MAP_POPULATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if fo.is_none() {
|
|
||||||
mmap_flags |= libc::MAP_ANONYMOUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
let region = GuestRegionMmap::new(
|
let region = GuestRegionMmap::new(
|
||||||
MmapRegion::build(fo, size, libc::PROT_READ | libc::PROT_WRITE, mmap_flags)
|
MmapRegion::build(fo, size, libc::PROT_READ | libc::PROT_WRITE, mmap_flags)
|
||||||
.map_err(Error::GuestMemoryRegion)?,
|
.map_err(Error::GuestMemoryRegion)?,
|
||||||
|
Loading…
Reference in New Issue
Block a user