add CommitResult::Marker; fix remove_child
@@ -63,6 +63,13 @@ impl VMOType {
_ => (PageStateTag::Init, Weak::new()),
}
}
+
+ fn is_hidden(&self) -> bool {
+ match self {
+ VMOType::Hidden{..} => true,
+ _ => false,
+ }
+ }
}
/// The main VM object type, holding a list of pages.
@@ -102,6 +109,16 @@ enum PageStateTag {
LeftSplit,
}
+impl PageStateTag {
+ fn negate(&self) -> Self {
+ match self {
+ PageStateTag::LeftSplit => PageStateTag::RightSplit,
+ PageStateTag::RightSplit => PageStateTag::LeftSplit,
+ PageStateTag::Init => unreachable!()
+ }
+ }
+}
+
impl PageState {
fn new(frame: PhysFrame) -> Self {
PageState {
@@ -255,6 +272,7 @@ impl VMObjectTrait for VMObjectPaged {
enum CommitResult {
Ok(PhysAddr),
CopyOnWrite(PhysFrame),
+ Marker(PhysFrame),
}
impl VMObjectPaged {
@@ -278,7 +296,11 @@ impl VMObjectPaged {
// lazy allocate zero frame
let target_frame = vmo_frame_alloc()?;
kernel_hal::frame_zero(target_frame.addr());
+ if inner.type_.is_hidden() {
+ return Ok(CommitResult::Marker(target_frame));
+ } else {
inner.frames.insert(page_idx, PageState::new(target_frame));
+ }
} else if no_frame {
// if page miss on this VMO, recursively commit to parent
let parent = inner.parent.as_ref().unwrap();
@@ -288,6 +310,18 @@ impl VMObjectPaged {
CommitResult::CopyOnWrite(frame) => {
inner.frames.insert(page_idx, PageState::new(frame));
}
+ r @ CommitResult::Marker(_) => {
+ if inner.type_.is_hidden() {
+ return Ok(r);
+ } else {
+ match r {
+ CommitResult::Marker(frame) => {
+ inner.frames.insert(page_idx, PageState::new(frame));
+ }
+ _ => unreachable!()
+ }
+ }
+ }
}
}
// now the page must hit on this VMO
@@ -386,7 +420,9 @@ impl VMObjectPagedInner {
break;
}
let idx = key - start;
- if !child.frames.contains_key(&idx) && value.tag == tag {
+ if value.tag == tag {
+ child.frames.insert(idx, value);
+ } else if !child.frames.contains_key(&idx) && value.tag != tag.negate() {
child.frames.insert(idx, value);
}
}
