Fix: fork vmo should be resizable if parent is resizable

This commit is contained in:
Jianfeng Jiang
2023-07-04 11:18:23 +08:00
committed by Tate, Hongliang Tian
parent 149e169b2c
commit 38a78cc3ce
2 changed files with 38 additions and 11 deletions

View File

@ -12,7 +12,7 @@ use crate::vm::{
use super::{is_intersected, Vmar, Vmar_}; use super::{is_intersected, Vmar, Vmar_};
use crate::vm::perms::VmPerms; use crate::vm::perms::VmPerms;
use crate::vm::vmar::Rights; use crate::vm::vmar::Rights;
use crate::vm::vmo::VmoRightsOp; use crate::vm::vmo::{VmoFlags, VmoRightsOp};
/// A VmMapping represents mapping a vmo into a vmar. /// A VmMapping represents mapping a vmo into a vmar.
/// A vmar can has multiple VmMappings, which means multiple vmos are mapped to a vmar. /// A vmar can has multiple VmMappings, which means multiple vmos are mapped to a vmar.
@ -276,7 +276,14 @@ impl VmMapping {
"fork vmo, parent size = 0x{:x}, map_to_addr = 0x{:x}", "fork vmo, parent size = 0x{:x}, map_to_addr = 0x{:x}",
vmo_size, map_to_addr vmo_size, map_to_addr
); );
let child_vmo = VmoChildOptions::new_cow(parent_vmo, 0..vmo_size).alloc()?; let child_vmo = {
let parent_flags = parent_vmo.flags();
let mut options = VmoChildOptions::new_cow(parent_vmo, 0..vmo_size);
if parent_flags.contains(VmoFlags::RESIZABLE) {
options = options.flags(VmoFlags::RESIZABLE);
}
options.alloc()?
};
let parent_vmar = new_parent.upgrade().unwrap(); let parent_vmar = new_parent.upgrade().unwrap();
let vm_space = parent_vmar.vm_space(); let vm_space = parent_vmar.vm_space();

View File

@ -293,7 +293,34 @@ impl VmoChildOptions<Rights, VmoSliceChild> {
} }
} }
impl<R> VmoChildOptions<R, VmoSliceChild> {
/// Flags that a VMO child inherits from its parent.
pub const PARENT_FLAGS_MASK: VmoFlags =
VmoFlags::from_bits(VmoFlags::CONTIGUOUS.bits | VmoFlags::DMA.bits).unwrap();
/// Flags that a VMO child may differ from its parent.
pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::empty();
/// Sets the VMO flags.
///
/// Only the flags among `Self::CHILD_FLAGS_MASK` may be set through this
/// method.
///
/// To set `VmoFlags::RESIZABLE`, the child must be COW.
///
/// The default value is `VmoFlags::empty()`.
pub fn flags(mut self, flags: VmoFlags) -> Self {
let inherited_flags = self.flags & Self::PARENT_FLAGS_MASK;
self.flags = inherited_flags | (flags & Self::CHILD_FLAGS_MASK);
self
}
}
impl<R> VmoChildOptions<R, VmoCowChild> { impl<R> VmoChildOptions<R, VmoCowChild> {
/// Flags that a VMO child inherits from its parent.
pub const PARENT_FLAGS_MASK: VmoFlags =
VmoFlags::from_bits(VmoFlags::CONTIGUOUS.bits | VmoFlags::DMA.bits).unwrap();
/// Flags that a VMO child may differ from its parent.
pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::RESIZABLE;
/// Creates a default set of options for creating a copy-on-write (COW) /// Creates a default set of options for creating a copy-on-write (COW)
/// VMO child. /// VMO child.
/// ///
@ -311,14 +338,6 @@ impl<R> VmoChildOptions<R, VmoCowChild> {
marker: PhantomData, marker: PhantomData,
} }
} }
}
impl<R, C> VmoChildOptions<R, C> {
/// Flags that a VMO child inherits from its parent.
pub const PARENT_FLAGS_MASK: VmoFlags =
VmoFlags::from_bits(VmoFlags::CONTIGUOUS.bits | VmoFlags::DMA.bits).unwrap();
/// Flags that a VMO child may differ from its parent.
pub const CHILD_FLAGS_MASK: VmoFlags = VmoFlags::RESIZABLE;
/// Sets the VMO flags. /// Sets the VMO flags.
/// ///
@ -329,7 +348,8 @@ impl<R, C> VmoChildOptions<R, C> {
/// ///
/// The default value is `VmoFlags::empty()`. /// The default value is `VmoFlags::empty()`.
pub fn flags(mut self, flags: VmoFlags) -> Self { pub fn flags(mut self, flags: VmoFlags) -> Self {
self.flags = flags & Self::CHILD_FLAGS_MASK; let inherited_flags = self.flags & Self::PARENT_FLAGS_MASK;
self.flags = inherited_flags | (flags & Self::CHILD_FLAGS_MASK);
self self
} }
} }