pub fn dirty_memory_range_table(
        &self,
    ) -> std::result::Result<MemoryRangeTable, MigratableError> {
        let page_size = 4096; // TODO: Does this need to vary?
        let mut table = MemoryRangeTable::default();
        let mut total_pages = 0;
        for r in &self.guest_ram_mappings {
            let dirty_bitmap = self.vm.get_dirty_log(r.slot, r.size).map_err(|e| {
                MigratableError::MigrateSend(anyhow!("Error getting VM dirty log {}", e))
            })?;

            let mut entry: Option<MemoryRange> = None;
            for (i, block) in dirty_bitmap.iter().enumerate() {
                if *block > 0 {
                    if let Some(entry) = &mut entry {
                        entry.length += 64 * page_size;
                    } else {
                        entry = Some(MemoryRange {
                            gpa: r.gpa + (64 * i as u64 * page_size),
                            length: 64 * page_size,
                        });
                    }
                    total_pages += block.count_ones() as u64;
                } else if let Some(entry) = entry.take() {
                    table.push(entry);
                }
            }
            if let Some(entry) = entry.take() {
                table.push(entry);
            }

            if table.regions().is_empty() {
                info!("Dirty Memory Range Table is empty");
            } else {
                info!("Dirty Memory Range Table:");
                let mut total_size = 0;
                for range in table.regions() {
                    info!("GPA: {:x} size: {} (KiB)", range.gpa, range.length / 1024);
                    total_size += range.length;
                }
                info!(
                    "Total pages: {} ({} KiB). Total size: {} KiB. Efficiency: {}%",
                    total_pages,
                    total_pages * page_size / 1024,
                    total_size / 1024,
                    (total_pages * page_size * 100) / total_size
                );
            }
        }
        Ok(table)
    }
// Generate a table for the pages that are dirty. The algorithm is currently
// very simple. If any page in a "block" of 64 pages is dirty then that whole
// "block" is added to the table. These "blocks" are also collapsed together if
// they are contiguous:
//
// For every block of 64 pages we check to see if there are any dirty pages in it
// if there are we increase the size of the current range if there is one, otherwise
// create a new range. If there are no dirty pages in the current "block" the range is
// closed if there is one and added to the table. After iterating through the dirty
// page bitmaps an open range will be closed and added to the table.
//
// This algorithm is very simple and could be refined to count the number of pages
// in the block and instead create smaller ranges covering those pages.
Generate a table for the pages that are dirty. The algorithm is currently
very simple. If any page in a "block" of 64 pages is dirty then that whole
"block" is added to the table. These "blocks" are also collapsed together if
they are contiguous.

For every block of 64 pages we check to see if there are any dirty pages in it
if there are we increase the size of the current range if there is one, otherwise
create a new range. If there are no dirty pages in the current "block" the range is
closed if there is one and added to the table. After iterating through the dirty
page bitmaps an open range will be closed and added to the table.

This algorithm is very simple and could be refined to count the number of pages
in the block and instead create smaller ranges covering those pages.
Generate a table for the pages that are dirty . The algorithm is currently very simple . If any page in a " block " of 64 pages is dirty then that whole " block " is added to the table . These " blocks " are also collapsed together if they are contiguous . For every block of 64 pages we check to see if there are any dirty pages in it if there are we increase the size of the current range if there is one otherwise create a new range . If there are no dirty pages in the current " block " the range is closed if there is one and added to the table . After iterating through the dirty page bitmaps an open range will be closed and added to the table . This algorithm is very simple and could be refined to count the number of pages in the block and instead create smaller ranges covering those pages .
pub fn dirty_memory_range_table(
        &self,
    ) -> std::result::Result<MemoryRangeTable, MigratableError> {
        let page_size = 4096; // TODO: Does this need to vary?
        let mut table = MemoryRangeTable::default();
        let mut total_pages = 0;
        for r in &self.guest_ram_mappings {
            let dirty_bitmap = self.vm.get_dirty_log(r.slot, r.size).map_err(|e| {
                MigratableError::MigrateSend(anyhow!("Error getting VM dirty log {}", e))
            })?;
            let mut entry: Option<MemoryRange> = None;
            for (i, block) in dirty_bitmap.iter().enumerate() {
                if *block > 0 {
                    if let Some(entry) = &mut entry {
                        entry.length += 64 * page_size;
                    } else {
                        entry = Some(MemoryRange {
                            gpa: r.gpa + (64 * i as u64 * page_size),
                            length: 64 * page_size,
                        });
                    }
                    total_pages += block.count_ones() as u64;
                } else if let Some(entry) = entry.take() {
                    table.push(entry);
                }
            }
            if let Some(entry) = entry.take() {
                table.push(entry);
            }
            if table.regions().is_empty() {
                info!("Dirty Memory Range Table is empty");
            } else {
                info!("Dirty Memory Range Table:");
                let mut total_size = 0;
                for range in table.regions() {
                    info!("GPA: {:x} size: {} (KiB)", range.gpa, range.length / 1024);
                    total_size += range.length;
                }
                info!(
                    "Total pages: {} ({} KiB). Total size: {} KiB. Efficiency: {}%",
                    total_pages,
                    total_pages * page_size / 1024,
                    total_size / 1024,
                    (total_pages * page_size * 100) / total_size
                );
            }
        }
        Ok(table)
    }
pub fn dirty_memory_range_table ( & self , ) -> std :: result :: Result < MemoryRangeTable , MigratableError > { let page_size = 4096 ; // TODO: Does this need to vary? let mut table = MemoryRangeTable :: default ( ) ; let mut total_pages = 0 ; for r in & self . guest_ram_mappings { let dirty_bitmap = self . vm . get_dirty_log ( r . slot , r . size ) . map_err ( | e | { MigratableError :: MigrateSend ( anyhow ! ( " " e ) ) } ) ? ; let mut entry : Option < MemoryRange > = None ; for ( i , block ) in dirty_bitmap . iter ( ) . enumerate ( ) { if * block > 0 { if let Some ( entry ) = & mut entry { entry . length += 64 * page_size ; } else { entry = Some ( MemoryRange { gpa : r . gpa + ( 64 * i as u64 * page_size ) , length : 64 * page_size , } ) ; } total_pages += block . count_ones ( ) as u64 ; } else if let Some ( entry ) = entry . take ( ) { table . push ( entry ) ; } } if let Some ( entry ) = entry . take ( ) { table . push ( entry ) ; } if table . regions ( ) . is_empty ( ) { info ! ( " " ) ; } else { info ! ( " " ) ; let mut total_size = 0 ; for range in table . regions ( ) { info ! ( " " range gpa range length 1024 ) ; total_size += range . length ; } info ! ( " " total_pages total_pages page_size 1024 total_size 1024 ( total_pages page_size 100 ) total_size ) ; } } Ok ( table ) }
Generate a table for the pages that are dirty.
Generate a table for the pages that are dirty .
&self
&self