in src/vmm/src/memory_snapshot.rs [119:177]
fn dump_dirty<T: std::io::Write + std::io::Seek>(
&self,
writer: &mut T,
dirty_bitmap: &DirtyBitmap,
) -> std::result::Result<(), Error> {
let mut writer_offset = 0;
let page_size = get_page_size().map_err(Error::PageSize)?;
self.iter()
.enumerate()
.try_for_each(|(slot, region)| {
let kvm_bitmap = dirty_bitmap.get(&slot).unwrap();
let firecracker_bitmap = region.bitmap();
let mut write_size = 0;
let mut dirty_batch_start: u64 = 0;
for (i, v) in kvm_bitmap.iter().enumerate() {
for j in 0..64 {
let is_kvm_page_dirty = ((v >> j) & 1u64) != 0u64;
let page_offset = ((i * 64) + j) * page_size;
let is_firecracker_page_dirty = firecracker_bitmap.dirty_at(page_offset);
if is_kvm_page_dirty || is_firecracker_page_dirty {
// We are at the start of a new batch of dirty pages.
if write_size == 0 {
// Seek forward over the unmodified pages.
writer
.seek(SeekFrom::Start(writer_offset + page_offset as u64))
.unwrap();
dirty_batch_start = page_offset as u64;
}
write_size += page_size;
} else if write_size > 0 {
// We are at the end of a batch of dirty pages.
region.write_all_to(
MemoryRegionAddress(dirty_batch_start),
writer,
write_size,
)?;
write_size = 0;
}
}
}
if write_size > 0 {
region.write_all_to(
MemoryRegionAddress(dirty_batch_start),
writer,
write_size,
)?;
}
writer_offset += region.len();
if let Some(bitmap) = firecracker_bitmap {
bitmap.reset();
}
Ok(())
})
.map_err(Error::WriteMemory)
}