xenclient: auto-retry mmapbatch when paging state issues occur

This commit is contained in:
Alex Zenla 2024-01-20 20:29:36 -08:00
parent 83264839dd
commit 001c22fd69
No known key found for this signature in database
GPG Key ID: 067B238899B51269
3 changed files with 83 additions and 6 deletions

View File

@ -13,7 +13,7 @@ use crate::sys::{
XEN_DOMCTL_SET_ADDRESS_SIZE, XEN_DOMCTL_UNPAUSEDOMAIN, XEN_MEM_MEMORY_MAP,
XEN_MEM_POPULATE_PHYSMAP,
};
use libc::{c_int, mmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
use libc::{c_int, mmap, usleep, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
use log::trace;
use nix::errno::Errno;
use std::error::Error;
@ -224,8 +224,62 @@ impl XenCall {
mfns: mfns.as_mut_ptr(),
errors: errors.as_mut_ptr(),
};
let result = sys::mmapbatch(self.handle.as_raw_fd(), &mut batch)?;
Ok(result as c_long)
let result = sys::mmapbatch(self.handle.as_raw_fd(), &mut batch);
if let Err(errno) = result {
if errno != Errno::ENOENT {
return Err(errno)?;
}
usleep(100);
let mut i: usize = 0;
let mut paged: usize = 0;
loop {
if errors[i] != libc::ENOENT {
i += 1;
continue;
}
paged += 1;
let mut batch = MmapBatch {
num: 1,
domid: domid as u16,
addr: addr + ((i as u64) << 12),
mfns: mfns.as_mut_ptr().add(i),
errors: errors.as_mut_ptr().add(i),
};
loop {
i += 1;
if i < num as usize {
if errors[i] != libc::ENOENT {
break;
}
batch.num += 1;
}
}
let result = sys::mmapbatch(self.handle.as_raw_fd(), &mut batch);
if let Err(n) = result {
if n != Errno::ENOENT {
return Err(n)?;
}
}
if i < num as usize {
break;
}
let count = result.unwrap();
if count <= 0 {
break;
}
}
return Ok(paged as c_long);
}
Ok(result.unwrap() as c_long)
}
}

View File

@ -110,6 +110,23 @@ impl XenClient {
..Default::default()
};
let domid = self.call.create_domain(domain)?;
match self.init(domid, &domain, config) {
Ok(_) => Ok(domid),
Err(err) => {
// ignore since destroying a domain is best
// effort when an error occurs
let _ = self.call.destroy_domain(domid);
Err(err)
}
}
}
fn init(
&mut self,
domid: u32,
domain: &CreateDomain,
config: &DomainConfig,
) -> Result<(), XenClientError> {
let backend_dom_path = self.store.get_domain_path(0)?;
let dom_path = self.store.get_domain_path(domid)?;
let uuid_string = Uuid::from_bytes(domain.handle).to_string();
@ -281,8 +298,7 @@ impl XenClient {
)?;
}
self.call.unpause_domain(domid)?;
Ok(domid)
Ok(())
}
fn disk_device_add(

View File

@ -86,7 +86,14 @@ impl XsdClient {
fn rm(&mut self, tx: u32, path: &str) -> Result<bool, XsdBusError> {
trace!("rm tx={tx} path={path}");
self.socket.send_single(tx, XSD_RM, path)?.parse_bool()
let result = self.socket.send_single(tx, XSD_RM, path);
if let Err(error) = result {
if error.to_string() == "ENOENT" {
return Ok(true);
}
return Err(error);
}
result.unwrap().parse_bool()
}
fn set_perms(