fn dump_dirty()

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)
    }