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

1
Cargo.lock generated
View File

@ -573,6 +573,7 @@ dependencies = [
"align_ext", "align_ext",
"ascii", "ascii",
"bitflags", "bitflags",
"bitvec",
"controlled", "controlled",
"core2", "core2",
"cpio-decoder", "cpio-decoder",

View File

@ -47,3 +47,8 @@ getrandom = { version = "0.2.10", default-features = false, features = ["rdrand"
[dependencies.lazy_static] [dependencies.lazy_static]
version = "1.0" version = "1.0"
features = ["spin_no_std"] features = ["spin_no_std"]
[dependencies.bitvec]
version = "1"
default-features = false
features = ["atomic", "alloc"]

View File

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