vmm: return error if prefaulting fails

Prefaulting pages was done on a best-effort basis before, meaning that
errors were ignored. This could lead to errors during runtime,
especially when used with hugepages, because there was no guarantee that
enough pages are available. With this change errors during prefaulting
will be reported.

Co-authored-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP sebastian.eydam@sap.com
Signed-off-by: Sebastian Eydam <sebastian.eydam@cyberus-technology.de>
This commit is contained in:
Sebastian Eydam
2026-02-26 16:52:42 +01:00
committed by Bo Chen
parent 494c30be19
commit 22cf10b6ab

View File

@@ -415,6 +415,10 @@ pub enum Error {
/// Memory size is misaligned with default page size or its hugepage size
#[error("Memory size is misaligned with default page size or its hugepage size")]
MisalignedMemorySize,
/// Failed to prefault memory
#[error("Failed to prefault memory")]
PrefaultMemory(#[source] io::Error),
}
impl From<UffdError> for Error {
@@ -2083,11 +2087,12 @@ impl MemoryManager {
let remainder = num_pages % num_threads;
let barrier = Arc::new(Barrier::new(num_threads));
thread::scope(|s| {
thread::scope(|s| -> Result<(), Error> {
let r = &region;
let mut handles = Vec::new();
for i in 0..num_threads {
let barrier = Arc::clone(&barrier);
s.spawn(move || {
let handle = s.spawn(move || {
// Wait until all threads have been spawned to avoid contention
// over mmap_sem between thread stack allocation and page faulting.
barrier.wait();
@@ -2100,11 +2105,26 @@ impl MemoryManager {
};
if ret != 0 {
let e = io::Error::last_os_error();
warn!("Failed to prefault pages: {e}");
return Err(e);
}
Ok(())
});
handles.push(handle);
}
});
for handle in handles {
handle
.join()
.map_err(|e| {
Error::PrefaultMemory(io::Error::other(format!(
"Prefault thread panicked: {e:?}"
)))
})?
.map_err(Error::PrefaultMemory)?;
}
Ok(())
})?;
}
info!(