Skip to content

Commit

Permalink
fix: Retry KVM_CREATE_VM on EINTR
Browse files Browse the repository at this point in the history
It is known that KVM_CREATE_VM fails with EINTR on heavily loaded
machines with many VMs. It might be a kernel bug but apparently has not
been fixed. To mitigate it, QEMU does an infinitely retry on EINTR.
Similar, do retries up to 5 times.

Signed-off-by: Takahiro Itazuri <[email protected]>
  • Loading branch information
zulinx86 committed Feb 21, 2025
1 parent 8757b06 commit fb23c4f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
2 changes: 1 addition & 1 deletion src/vmm/src/vstate/vm/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub enum ArchVmError {
impl ArchVm {
/// Create a new `Vm` struct.
pub fn new(kvm: &Kvm) -> Result<ArchVm, VmError> {
let fd = kvm.fd.create_vm().map_err(VmError::CreateVm)?;
let fd = Self::create_vm(kvm)?;
Ok(ArchVm {
fd,
irqchip_handle: None,
Expand Down
25 changes: 25 additions & 0 deletions src/vmm/src/vstate/vm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use kvm_bindings::{kvm_userspace_memory_region, KVM_MEM_LOG_DIRTY_PAGES};
use kvm_ioctls::VmFd;
use vmm_sys_util::eventfd::EventFd;

use crate::logger::info;
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRegion};

#[cfg(target_arch = "x86_64")]
Expand Down Expand Up @@ -42,6 +43,30 @@ pub enum VmError {

/// Contains Vm functions that are usable across CPU architectures
impl Vm {
fn create_vm(kvm: &crate::vstate::kvm::Kvm) -> Result<VmFd, VmError> {
// It is known that KVM_CREATE_VM spuriously fails with EINTR on heavily loaded machines
// with many VMs. It might be a kernel bug but apparently has not been fixed.
//
// To mitigate it, QEMU does an inifinite retry on EINTR:
// - https://github.com/qemu/qemu/commit/94ccff133820552a859c0fb95e33a539e0b90a75
// - https://github.com/qemu/qemu/commit/bbde13cd14ad4eec18529ce0bf5876058464e124
//
// Similarly, we do retries up to 5 times until the bug is fixed.
const MAX_ATTEMPTS: u32 = 5;
for attempt in 1..=MAX_ATTEMPTS {
match kvm.fd.create_vm() {
Ok(fd) => return Ok(fd),
Err(e) if e.errno() == libc::EINTR && attempt < MAX_ATTEMPTS => {
info!("Attemp #{attempt} of KVM_CREATE_VM returned EINTR");

Check warning on line 60 in src/vmm/src/vstate/vm/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vm/mod.rs#L59-L60

Added lines #L59 - L60 were not covered by tests
// Exponential backoff (1us, 2us, 4us, and 8us => 15us in total)
std::thread::sleep(std::time::Duration::from_micros(2u64.pow(attempt - 1)));

Check warning on line 62 in src/vmm/src/vstate/vm/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vm/mod.rs#L62

Added line #L62 was not covered by tests
}
Err(e) => return Err(VmError::CreateVm(e)),

Check warning on line 64 in src/vmm/src/vstate/vm/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vm/mod.rs#L64

Added line #L64 was not covered by tests
}
}
unreachable!();

Check warning on line 67 in src/vmm/src/vstate/vm/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/vmm/src/vstate/vm/mod.rs#L67

Added line #L67 was not covered by tests
}

/// Creates the specified number of [`Vcpu`]s.
///
/// The returned [`EventFd`] is written to whenever any of the vcpus exit.
Expand Down
3 changes: 2 additions & 1 deletion src/vmm/src/vstate/vm/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ pub struct ArchVm {
impl ArchVm {
/// Create a new `Vm` struct.
pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result<ArchVm, VmError> {
let fd = kvm.fd.create_vm().map_err(VmError::CreateVm)?;
let fd = Self::create_vm(kvm)?;

let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?;

fd.set_tss_address(u64_to_usize(crate::arch::x86_64::layout::KVM_TSS_ADDRESS))
Expand Down

0 comments on commit fb23c4f

Please sign in to comment.