pub struct DirtyBitmap { /* private fields */ }Expand description
Box<[AtomicU64]> shadow bitmap of dirty tracking pages.
The map covers [ram_start, ram_start + ram_size). set_dirty is called from
the vCPU exit handler; drain is called by the snapshot writer. Both are
lock-free.
Implementations§
Source§impl DirtyBitmap
impl DirtyBitmap
Sourcepub fn new(
ram_start: u64,
ram_size: u64,
page_size: u64,
) -> Result<Self, SnapshotError>
pub fn new( ram_start: u64, ram_size: u64, page_size: u64, ) -> Result<Self, SnapshotError>
Build a bitmap covering [ram_start, ram_start + ram_size) at page_size.
§Errors
SnapshotError::InvalidPath (re-used for “rejected configuration”) if
page_size is not a power of two, the range is empty, or the range overflows.
Sourcepub const fn page_count(&self) -> u64
pub const fn page_count(&self) -> u64
Number of tracked pages.
Sourcepub fn page_shift(&self) -> u32
pub fn page_shift(&self) -> u32
log2(page_size) — used by callers that compute the FAR-to-bit-index shift.
Sourcepub fn page_index_of(&self, addr: u64) -> Option<u64>
pub fn page_index_of(&self, addr: u64) -> Option<u64>
Compute the bit index of the page containing addr.
Returns None if addr is outside the tracked range.
Sourcepub fn set_dirty(&self, addr: u64) -> bool
pub fn set_dirty(&self, addr: u64) -> bool
Set the dirty bit for the page containing addr. Idempotent.
Returns true if the bit transitioned from clean to dirty.
Sourcepub fn set_dirty_by_index(&self, page: u64) -> bool
pub fn set_dirty_by_index(&self, page: u64) -> bool
Set a specific page’s dirty bit. Same return semantics as Self::set_dirty.
Sourcepub fn is_dirty_by_index(&self, page: u64) -> bool
pub fn is_dirty_by_index(&self, page: u64) -> bool
Same as Self::is_dirty but accepts a pre-computed page index.
Sourcepub fn drain(&self) -> Vec<u64>
pub fn drain(&self) -> Vec<u64>
Atomically swap each word to zero, returning a list of dirty page indices.
The acquire ordering on the swap pairs with the release on set_dirty’s
fetch_or (Relaxed is sufficient there because the only consumer is this
drain on the snapshot path, and the drain seq-cst-like ordering is owed by
the surrounding pause/resume vCPU dance, not by the bitmap itself; we use
Acquire here to synchronize-with any future code that relaxes the surrounding
vCPU coordination).
Sourcepub fn drain_into<F: FnMut(u64)>(&self, callback: F)
pub fn drain_into<F: FnMut(u64)>(&self, callback: F)
Drain into a callback, avoiding the intermediate Vec allocation. Used by the memory-file writer’s hot path.
Sourcepub fn fold_into_finer(&self, fine: &DirtyBitmap) -> Result<(), SnapshotError>
pub fn fold_into_finer(&self, fine: &DirtyBitmap) -> Result<(), SnapshotError>
Fold all coarse-block dirty bits into a finer-grained bitmap.
When the heuristic steps down a region from 2 MiB to 16 KiB, the coarse bitmap’s set bits each correspond to a 2 MiB block: every fine page in that block becomes dirty. This preserves snapshot coverage across the transition.
fine must cover the same [ram_start, ram_start + ram_size) and have a
strictly smaller page_size.
§Errors
SnapshotError::InvalidPath if the geometry doesn’t match.