Drop parent once all inherited pages is committed by child

This commit is contained in:
Jianfeng Jiang
2023-07-04 10:44:07 +08:00
committed by Tate, Hongliang Tian
parent ad0ab0898a
commit 149e169b2c
3 changed files with 27 additions and 1 deletions

View File

@ -3,6 +3,8 @@
use core::ops::Range;
use align_ext::AlignExt;
use bitvec::bitvec;
use bitvec::vec::BitVec;
use jinux_frame::vm::{VmAllocOptions, VmFrameVec, VmIo};
use jinux_rights::Rights;
@ -167,6 +169,8 @@ struct InheritedPages {
/// page with index `idx + parent_page_idx_offset` in parent vmo
parent_page_idx_offset: usize,
is_copy_on_write: bool,
/// The pages already committed by child
committed_pages: BitVec,
}
impl InheritedPages {
@ -176,11 +180,13 @@ impl InheritedPages {
parent_page_idx_offset: usize,
is_copy_on_write: bool,
) -> Self {
let committed_pages = bitvec![0; page_range.len()];
Self {
parent: Some(parent),
page_range,
parent_page_idx_offset,
is_copy_on_write,
committed_pages,
}
}
@ -236,6 +242,19 @@ impl InheritedPages {
fn should_child_commit_page(&self, write_page: bool) -> bool {
!self.is_copy_on_write || (self.is_copy_on_write && write_page)
}
fn mark_page_as_commited(&mut self, page_idx: usize) {
if !self.contains_page(page_idx) {
return;
}
let idx = page_idx - self.page_range.start;
debug_assert_eq!(self.committed_pages[idx], false);
debug_assert!(self.parent.is_some());
self.committed_pages.set(idx, true);
if self.committed_pages.count_ones() == self.page_range.len() {
self.parent.take();
}
}
}
impl VmoInner {
@ -292,10 +311,11 @@ impl VmoInner {
return Ok(frames);
}
let inherited_pages = self.inherited_pages.as_ref().unwrap();
let inherited_pages = self.inherited_pages.as_mut().unwrap();
let frame = inherited_pages.get_frame_from_parent(page_idx, write_page, commit_if_none)?;
if inherited_pages.should_child_commit_page(write_page) {
inherited_pages.mark_page_as_commited(page_idx);
self.insert_frame(page_idx, frame.clone());
}