sys_util: Add ability to madvise a region

Add functions to let the kernel know a given range of memory isn't
needed currently. This function will result in `madvise(DONTNEED)`.

The ability to signal memory as not needed will be used by the balloon
driver to allow system memory to be redistributed away from the VM.

Change-Id: I4ca56e09010eec33989824f5738db4a4be0ec428
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/759305
Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
Dylan Reid 2017-11-06 14:06:58 -08:00 committed by chrome-bot
parent fedb675ed5
commit 2415ef6988
2 changed files with 32 additions and 0 deletions

View file

@ -105,6 +105,15 @@ impl GuestMemory {
self.regions.len()
}
/// Madvise away the address range in the host that is associated with the given guest range.
pub fn dont_need_range(&self, addr: GuestAddress, count: usize) -> Result<()> {
self.do_in_region(addr, move |mapping, offset| {
mapping
.dont_need_range(offset, count)
.map_err(|e| Error::MemoryAccess(addr, e))
})
}
/// Perform the specified action on each region's addresses.
pub fn with_regions<F, E>(&self, cb: F) -> result::Result<(), E>
where F: Fn(usize, GuestAddress, usize, usize) -> result::Result<(), E>

View file

@ -299,6 +299,29 @@ impl MemoryMapping {
Ok(())
}
/// Uses madvise to tell the kernel the specified range won't be needed soon.
pub fn dont_need_range(&self, mem_offset: usize, count: usize) -> Result<()> {
let mem_end = match mem_offset.checked_add(count) {
None => return Err(Error::InvalidRange(mem_offset, count)),
Some(m) => m,
};
if mem_end > self.size() {
return Err(Error::InvalidRange(mem_offset, count));
}
let ret = unsafe {
// madvising away the region is the same as the guest changing it.
// Next time it is read, it may return zero pages.
libc::madvise((self.addr as usize + mem_offset) as *mut _,
count,
libc::MADV_DONTNEED)
};
if ret < 0 {
Err(Error::InvalidRange(mem_offset, count))
} else {
Ok(())
}
}
unsafe fn as_slice(&self) -> &[u8] {
// This is safe because we mapped the area at addr ourselves, so this slice will not
// overflow. However, it is possible to alias.