vmm: memory: Extend new() to support external backing files

Whenever a MemoryManager is restored from a snapshot, the memory regions
associated with it might need to directly back the mapped memory for
increased performances. If that's the case, a list of external regions
is provided and the MemoryManager should simply ignore what's coming
from the MemoryConfig.

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-04-07 11:19:28 +02:00
parent ee5a041a0f
commit d771223b2f
2 changed files with 35 additions and 11 deletions

View File

@ -110,6 +110,10 @@ pub enum Error {
/// Cannot create the system allocator /// Cannot create the system allocator
CreateSystemAllocator, CreateSystemAllocator,
/// The number of external backing files doesn't match the number of
/// memory regions.
InvalidAmountExternalBackingFiles,
} }
pub fn get_host_cpu_phys_bits() -> u8 { pub fn get_host_cpu_phys_bits() -> u8 {
@ -221,7 +225,11 @@ impl BusDevice for MemoryManager {
} }
impl MemoryManager { impl MemoryManager {
pub fn new(fd: Arc<VmFd>, config: &MemoryConfig) -> Result<Arc<Mutex<MemoryManager>>, Error> { pub fn new(
fd: Arc<VmFd>,
config: &MemoryConfig,
ext_regions: Option<Vec<MemoryRegion>>,
) -> Result<Arc<Mutex<MemoryManager>>, Error> {
// Init guest memory // Init guest memory
let arch_mem_regions = arch::arch_memory_regions(config.size); let arch_mem_regions = arch::arch_memory_regions(config.size);
@ -232,6 +240,20 @@ impl MemoryManager {
.collect(); .collect();
let mut mem_regions = Vec::new(); let mut mem_regions = Vec::new();
if let Some(ext_regions) = &ext_regions {
if ram_regions.len() > ext_regions.len() {
return Err(Error::InvalidAmountExternalBackingFiles);
}
for region in ext_regions.iter() {
mem_regions.push(MemoryManager::create_ram_region(
&Some(region.backing_file.clone()),
region.start_addr,
region.size as usize,
true,
)?);
}
} else {
for region in ram_regions.iter() { for region in ram_regions.iter() {
mem_regions.push(MemoryManager::create_ram_region( mem_regions.push(MemoryManager::create_ram_region(
&config.file, &config.file,
@ -240,6 +262,7 @@ impl MemoryManager {
false, false,
)?); )?);
} }
}
let guest_memory = let guest_memory =
GuestMemoryMmap::from_arc_regions(mem_regions).map_err(Error::GuestMemory)?; GuestMemoryMmap::from_arc_regions(mem_regions).map_err(Error::GuestMemory)?;
@ -361,7 +384,7 @@ impl MemoryManager {
config: &MemoryConfig, config: &MemoryConfig,
source_url: &str, source_url: &str,
) -> Result<Arc<Mutex<MemoryManager>>, Error> { ) -> Result<Arc<Mutex<MemoryManager>>, Error> {
let memory_manager = MemoryManager::new(fd, config)?; let memory_manager = MemoryManager::new(fd, config, None)?;
let url = Url::parse(source_url).unwrap(); let url = Url::parse(source_url).unwrap();
/* url must be valid dir which is verified in recv_vm_snapshot() */ /* url must be valid dir which is verified in recv_vm_snapshot() */

View File

@ -360,7 +360,8 @@ impl Vm {
vmm_path: PathBuf, vmm_path: PathBuf,
) -> Result<Self> { ) -> Result<Self> {
let (kvm, fd) = Vm::kvm_new()?; let (kvm, fd) = Vm::kvm_new()?;
let memory_manager = MemoryManager::new(fd.clone(), &config.lock().unwrap().memory.clone()) let memory_manager =
MemoryManager::new(fd.clone(), &config.lock().unwrap().memory.clone(), None)
.map_err(Error::MemoryManager)?; .map_err(Error::MemoryManager)?;
Vm::new_from_memory_manager( Vm::new_from_memory_manager(