diff --git a/xencall/src/lib.rs b/xencall/src/lib.rs index ae4e224..9db68f4 100644 --- a/xencall/src/lib.rs +++ b/xencall/src/lib.rs @@ -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) } } diff --git a/xenclient/src/lib.rs b/xenclient/src/lib.rs index 26e6a3f..79127e1 100644 --- a/xenclient/src/lib.rs +++ b/xenclient/src/lib.rs @@ -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( diff --git a/xenstore/src/client.rs b/xenstore/src/client.rs index 9c4344e..ad65693 100644 --- a/xenstore/src/client.rs +++ b/xenstore/src/client.rs @@ -86,7 +86,14 @@ impl XsdClient { fn rm(&mut self, tx: u32, path: &str) -> Result { 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(