Remove `VmMapping::inode`
This commit is contained in:
parent
894f6ba9b4
commit
8297da7247
|
|
@ -12,12 +12,13 @@ use super::{inode_handle::InodeHandle, path::Path};
|
|||
use crate::{
|
||||
fs::{
|
||||
file_table::FdFlags,
|
||||
utils::{AccessMode, FallocMode, Inode, SeekFrom, StatusFlags},
|
||||
utils::{AccessMode, FallocMode, SeekFrom, StatusFlags},
|
||||
},
|
||||
net::socket::Socket,
|
||||
prelude::*,
|
||||
process::signal::Pollable,
|
||||
util::ioctl::RawIoctl,
|
||||
vm::vmo::Vmo,
|
||||
};
|
||||
|
||||
/// The basic operations defined on a file
|
||||
|
|
@ -154,8 +155,8 @@ impl dyn FileLike {
|
|||
/// An object that may be memory mapped into the user address space.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Mappable {
|
||||
/// An inode object.
|
||||
Inode(Arc<dyn Inode>),
|
||||
/// A VMO (i.e., page cache).
|
||||
Vmo(Arc<Vmo>),
|
||||
/// An MMIO region.
|
||||
IoMem(IoMem),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -328,10 +328,10 @@ impl FileLike for InodeHandle {
|
|||
}
|
||||
|
||||
let inode = self.path.inode();
|
||||
if inode.page_cache().is_some() {
|
||||
if let Some(ref vmo) = inode.page_cache() {
|
||||
// If the inode has a page cache, it is a file-backed mapping and
|
||||
// we directly return the corresponding inode.
|
||||
Ok(Mappable::Inode(inode.clone()))
|
||||
// we return the VMO as the mappable object.
|
||||
Ok(Mappable::Vmo(vmo.clone()))
|
||||
} else if let Some(ref file_io) = self.file_io {
|
||||
// Otherwise, it is a special file (e.g. device file) and we should
|
||||
// return the file-specific mappable object.
|
||||
|
|
|
|||
|
|
@ -68,13 +68,10 @@ pub struct VmMapping {
|
|||
/// The start of the virtual address maps to the start of the range
|
||||
/// specified in the mapped object.
|
||||
mapped_mem: MappedMemory,
|
||||
/// The inode of the file that backs the mapping.
|
||||
///
|
||||
/// If the inode is `Some`, it means that the mapping is file-backed.
|
||||
/// And the `mapped_mem` field must be the page cache of the inode, i.e.
|
||||
/// [`MappedMemory::Vmo`].
|
||||
inode: Option<Arc<dyn Inode>>,
|
||||
/// The path of the file that backs the mapping.
|
||||
///
|
||||
/// If the mapping is VMO-backed, the `mapped_mem` field should be the
|
||||
/// page cache of the inode in the path.
|
||||
path: Option<Path>,
|
||||
/// Whether the mapping is shared.
|
||||
///
|
||||
|
|
@ -99,12 +96,10 @@ impl Interval<Vaddr> for VmMapping {
|
|||
/***************************** Basic methods *********************************/
|
||||
|
||||
impl VmMapping {
|
||||
#[expect(clippy::too_many_arguments)]
|
||||
pub(super) fn new(
|
||||
map_size: NonZeroUsize,
|
||||
map_to_addr: Vaddr,
|
||||
mapped_mem: MappedMemory,
|
||||
inode: Option<Arc<dyn Inode>>,
|
||||
path: Option<Path>,
|
||||
is_shared: bool,
|
||||
handle_page_faults_around: bool,
|
||||
|
|
@ -114,7 +109,6 @@ impl VmMapping {
|
|||
map_size,
|
||||
map_to_addr,
|
||||
mapped_mem,
|
||||
inode,
|
||||
path,
|
||||
is_shared,
|
||||
handle_page_faults_around,
|
||||
|
|
@ -125,7 +119,6 @@ impl VmMapping {
|
|||
pub(super) fn new_fork(&self) -> VmMapping {
|
||||
VmMapping {
|
||||
mapped_mem: self.mapped_mem.dup(),
|
||||
inode: self.inode.clone(),
|
||||
path: self.path.clone(),
|
||||
..*self
|
||||
}
|
||||
|
|
@ -159,7 +152,7 @@ impl VmMapping {
|
|||
|
||||
/// Returns the inode of the file that backs the mapping.
|
||||
pub fn inode(&self) -> Option<&Arc<dyn Inode>> {
|
||||
self.inode.as_ref()
|
||||
self.path.as_ref().map(|path| path.inode())
|
||||
}
|
||||
|
||||
/// Returns a reference to the VMO if this mapping is VMO-backed.
|
||||
|
|
@ -641,7 +634,6 @@ impl VmMapping {
|
|||
map_to_addr: self.map_to_addr,
|
||||
map_size: NonZeroUsize::new(left_size).unwrap(),
|
||||
mapped_mem: l_mapped_mem,
|
||||
inode: self.inode.clone(),
|
||||
path: self.path.clone(),
|
||||
..self
|
||||
};
|
||||
|
|
@ -964,7 +956,6 @@ fn try_merge(left: &VmMapping, right: &VmMapping) -> Option<VmMapping> {
|
|||
Some(VmMapping {
|
||||
map_size,
|
||||
mapped_mem,
|
||||
inode: left.inode.clone(),
|
||||
path: left.path.clone(),
|
||||
..*left
|
||||
})
|
||||
|
|
|
|||
|
|
@ -52,7 +52,6 @@ impl Vmar {
|
|||
/// to overlap with any existing mapping, either.
|
||||
pub struct VmarMapOptions<'a> {
|
||||
parent: &'a Vmar,
|
||||
vmo: Option<Arc<Vmo>>,
|
||||
mappable: Option<Mappable>,
|
||||
path: Option<Path>,
|
||||
perms: VmPerms,
|
||||
|
|
@ -74,7 +73,6 @@ impl<'a> VmarMapOptions<'a> {
|
|||
pub fn new(parent: &'a Vmar, size: usize, perms: VmPerms) -> Self {
|
||||
Self {
|
||||
parent,
|
||||
vmo: None,
|
||||
mappable: None,
|
||||
path: None,
|
||||
perms,
|
||||
|
|
@ -116,30 +114,37 @@ impl<'a> VmarMapOptions<'a> {
|
|||
/// oversized mappings can reserve space for future expansions.
|
||||
///
|
||||
/// The [`Vmo`] of a mapping will be implicitly set if [`Self::mappable`] is
|
||||
/// set with a [`Mappable::Inode`].
|
||||
/// set with a [`Mappable::Vmo`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if a [`Mappable`] is already provided.
|
||||
/// This function panics if a [`Vmo`] or [`Mappable`] is already provided.
|
||||
pub fn vmo(mut self, vmo: Arc<Vmo>) -> Self {
|
||||
if self.mappable.is_some() {
|
||||
panic!("Cannot set `vmo` when `mappable` is already set");
|
||||
}
|
||||
self.vmo = Some(vmo);
|
||||
self.mappable = Some(Mappable::Vmo(vmo));
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the [`Path`] of the mapping.
|
||||
///
|
||||
/// If a [`Vmo`] is specified, the inode behind the [`Path`] must have
|
||||
/// the [`Vmo`] as the page cache.
|
||||
///
|
||||
/// The [`Path`] of a mapping will be implicitly set if [`Self::mappable`]
|
||||
/// is set.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if a [`Mappable`] is already provided.
|
||||
/// This function panics if a [`Path`] is already provided.
|
||||
pub fn path(mut self, path: Path) -> Self {
|
||||
if self.mappable.is_some() {
|
||||
panic!("Cannot set `path` when `mappable` is already set");
|
||||
if self.path.is_some() {
|
||||
panic!("Cannot set `path` when `path` is already set");
|
||||
}
|
||||
self.path = Some(path);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
|
@ -206,37 +211,30 @@ impl<'a> VmarMapOptions<'a> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Binds memory to map based on the [`Mappable`] enum.
|
||||
/// Binds the file's [`Mappable`] object to the mapping and sets the
|
||||
/// [`Path`] of the mapping.
|
||||
///
|
||||
/// This method accepts file-specific details, like a page cache (inode)
|
||||
/// or I/O memory, but not both simultaneously.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if a [`Vmo`], [`Path`] or [`Mappable`] is already provided.
|
||||
/// This function panics if a [`Vmo`], [`Mappable`], or [`Path`] is already
|
||||
/// provided.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function returns an error if the file does not have a corresponding
|
||||
/// mappable object of [`crate::fs::file_handle::Mappable`].
|
||||
/// mappable object of [`Mappable`].
|
||||
pub fn mappable(mut self, file: &dyn FileLike) -> Result<Self> {
|
||||
if self.vmo.is_some() {
|
||||
panic!("Cannot set `mappable` when `vmo` is already set");
|
||||
if self.mappable.is_some() {
|
||||
panic!("Cannot set `mappable` when `mappable` is already set");
|
||||
}
|
||||
if self.path.is_some() {
|
||||
panic!("Cannot set `mappable` when `path` is already set");
|
||||
}
|
||||
if self.mappable.is_some() {
|
||||
panic!("Cannot set `mappable` when `mappable` is already set");
|
||||
}
|
||||
|
||||
let mappable = file.mappable()?;
|
||||
|
||||
// Verify whether the page cache inode is valid.
|
||||
if let Mappable::Inode(ref inode) = mappable {
|
||||
self.vmo = Some(inode.page_cache().expect("Map an inode without page cache"));
|
||||
}
|
||||
|
||||
self.mappable = Some(mappable);
|
||||
self.path = Some(file.path().clone());
|
||||
|
||||
|
|
@ -252,7 +250,6 @@ impl<'a> VmarMapOptions<'a> {
|
|||
self.check_options()?;
|
||||
let Self {
|
||||
parent,
|
||||
vmo,
|
||||
mappable,
|
||||
path,
|
||||
perms,
|
||||
|
|
@ -310,12 +307,14 @@ impl<'a> VmarMapOptions<'a> {
|
|||
};
|
||||
|
||||
// Parse the `Mappable` and prepare the `MappedMemory`.
|
||||
let (mapped_mem, inode, io_mem) = if let Some(mappable) = mappable {
|
||||
// Handle the memory backed by device or page cache.
|
||||
match mappable {
|
||||
Mappable::Inode(inode) => {
|
||||
let is_writable_tracked = if let Some(memfd_inode) =
|
||||
inode.downcast_ref::<MemfdInode>()
|
||||
let (mapped_mem, io_mem) = match mappable {
|
||||
Some(Mappable::Vmo(vmo)) => {
|
||||
if let Some(ref path) = path {
|
||||
debug_assert!(Arc::ptr_eq(&vmo, &path.inode().page_cache().unwrap()));
|
||||
}
|
||||
|
||||
let is_writable_tracked = if let Some(ref path) = path
|
||||
&& let Some(memfd_inode) = path.inode().downcast_ref::<MemfdInode>()
|
||||
&& is_shared
|
||||
&& may_perms.contains(VmPerms::MAY_WRITE)
|
||||
{
|
||||
|
|
@ -325,25 +324,12 @@ impl<'a> VmarMapOptions<'a> {
|
|||
false
|
||||
};
|
||||
|
||||
// Since `Mappable::Inode` is provided, it is
|
||||
// reasonable to assume that the VMO is provided.
|
||||
let mapped_mem = MappedMemory::Vmo(MappedVmo::new(
|
||||
vmo.unwrap(),
|
||||
vmo_offset,
|
||||
is_writable_tracked,
|
||||
)?);
|
||||
(mapped_mem, Some(inode), None)
|
||||
let mapped_mem =
|
||||
MappedMemory::Vmo(MappedVmo::new(vmo, vmo_offset, is_writable_tracked)?);
|
||||
(mapped_mem, None)
|
||||
}
|
||||
Mappable::IoMem(iomem) => (MappedMemory::Device, None, Some(iomem)),
|
||||
}
|
||||
} else if let Some(vmo) = vmo {
|
||||
(
|
||||
MappedMemory::Vmo(MappedVmo::new(vmo, vmo_offset, false)?),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
} else {
|
||||
(MappedMemory::Anonymous, None, None)
|
||||
Some(Mappable::IoMem(io_mem)) => (MappedMemory::Device, Some(io_mem)),
|
||||
None => (MappedMemory::Anonymous, None),
|
||||
};
|
||||
|
||||
// Build the mapping.
|
||||
|
|
@ -351,7 +337,6 @@ impl<'a> VmarMapOptions<'a> {
|
|||
NonZeroUsize::new(map_size).unwrap(),
|
||||
map_to_addr,
|
||||
mapped_mem,
|
||||
inode,
|
||||
path,
|
||||
is_shared,
|
||||
handle_page_faults_around,
|
||||
|
|
|
|||
Loading…
Reference in New Issue