vmm, virtio-devices: mem: Don't use MADV_DONTNEED on hugepages

This commit introduces a new information to the VirtioMemZone structure
in order to know if the memory zone is backed by hugepages.

Based on this new information, the virtio-mem device is now able to
determine if madvise(MADV_DONTNEED) should be performed or not. The
madvise documentation specifies that MADV_DONTNEED advice will fail if
the memory range has been allocated with some hugepages.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
Signed-off-by: Hui Zhu <teawater@antfin.com>
This commit is contained in:
Sebastien Boeuf 2021-02-03 09:46:14 +01:00 committed by Rob Bradford
parent 54f814f34a
commit c397c9c95e
3 changed files with 28 additions and 11 deletions

View File

@ -415,10 +415,12 @@ struct MemEpollHandler {
queue_evt: EventFd, queue_evt: EventFd,
kill_evt: EventFd, kill_evt: EventFd,
pause_evt: EventFd, pause_evt: EventFd,
hugepages: bool,
} }
impl MemEpollHandler { impl MemEpollHandler {
fn discard_memory_range(&self, offset: u64, size: u64) -> Result<(), Error> { fn discard_memory_range(&self, offset: u64, size: u64) -> Result<(), Error> {
// Use fallocate if the memory region is backed by a file.
if let Some(fd) = self.host_fd { if let Some(fd) = self.host_fd {
let res = unsafe { let res = unsafe {
libc::fallocate64( libc::fallocate64(
@ -434,17 +436,22 @@ impl MemEpollHandler {
return Err(Error::DiscardMemoryRange(err)); return Err(Error::DiscardMemoryRange(err));
} }
} }
let res = unsafe {
libc::madvise( // Only use madvise if the memory region is not allocated with
(self.host_addr + offset) as *mut libc::c_void, // hugepages.
size as libc::size_t, if !self.hugepages {
libc::MADV_DONTNEED, let res = unsafe {
) libc::madvise(
}; (self.host_addr + offset) as *mut libc::c_void,
if res != 0 { size as libc::size_t,
let err = io::Error::last_os_error(); libc::MADV_DONTNEED,
error!("Advising kernel about pages range failed: {}", err); )
return Err(Error::DiscardMemoryRange(err)); };
if res != 0 {
let err = io::Error::last_os_error();
error!("Advising kernel about pages range failed: {}", err);
return Err(Error::DiscardMemoryRange(err));
}
} }
Ok(()) Ok(())
@ -667,6 +674,7 @@ pub struct Mem {
host_fd: Option<RawFd>, host_fd: Option<RawFd>,
config: Arc<Mutex<VirtioMemConfig>>, config: Arc<Mutex<VirtioMemConfig>>,
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
hugepages: bool,
} }
impl Mem { impl Mem {
@ -678,6 +686,7 @@ impl Mem {
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
numa_node_id: Option<u16>, numa_node_id: Option<u16>,
initial_size: u64, initial_size: u64,
hugepages: bool,
) -> io::Result<Mem> { ) -> io::Result<Mem> {
let region_len = region.len(); let region_len = region.len();
@ -748,6 +757,7 @@ impl Mem {
host_fd, host_fd,
config: Arc::new(Mutex::new(config)), config: Arc::new(Mutex::new(config)),
seccomp_action, seccomp_action,
hugepages,
}) })
} }
} }
@ -827,6 +837,7 @@ impl VirtioDevice for Mem {
queue_evt: queue_evts.remove(0), queue_evt: queue_evts.remove(0),
kill_evt, kill_evt,
pause_evt, pause_evt,
hugepages: self.hugepages,
}; };
handler handler

View File

@ -2347,6 +2347,7 @@ impl DeviceManager {
self.seccomp_action.clone(), self.seccomp_action.clone(),
node_id, node_id,
virtio_mem_zone.hotplugged_size(), virtio_mem_zone.hotplugged_size(),
virtio_mem_zone.hugepages(),
) )
.map_err(DeviceManagerError::CreateVirtioMem)?, .map_err(DeviceManagerError::CreateVirtioMem)?,
)); ));

View File

@ -72,6 +72,7 @@ pub struct VirtioMemZone {
region: Arc<GuestRegionMmap>, region: Arc<GuestRegionMmap>,
resize_handler: virtio_devices::Resize, resize_handler: virtio_devices::Resize,
hotplugged_size: u64, hotplugged_size: u64,
hugepages: bool,
} }
impl VirtioMemZone { impl VirtioMemZone {
@ -84,6 +85,9 @@ impl VirtioMemZone {
pub fn hotplugged_size(&self) -> u64 { pub fn hotplugged_size(&self) -> u64 {
self.hotplugged_size self.hotplugged_size
} }
pub fn hugepages(&self) -> bool {
self.hugepages
}
} }
#[derive(Default)] #[derive(Default)]
@ -684,6 +688,7 @@ impl MemoryManager {
resize_handler: virtio_devices::Resize::new() resize_handler: virtio_devices::Resize::new()
.map_err(Error::EventFdFail)?, .map_err(Error::EventFdFail)?,
hotplugged_size: zone.hotplugged_size.unwrap_or(0), hotplugged_size: zone.hotplugged_size.unwrap_or(0),
hugepages: zone.hugepages,
}); });
start_of_device_area = start_addr start_of_device_area = start_addr