vfs: check mountpoint before instantiating a new filesystem
This commit is contained in:
parent
df0a48ca42
commit
595504b371
@ -91,7 +91,7 @@ impl Filesystem for Ext2Fs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ext2Fs {
|
impl Ext2Fs {
|
||||||
pub async fn create<'a, I: Iterator<Item = FilesystemMountOption<'a>>>(
|
pub async fn create<'a, I: IntoIterator<Item = FilesystemMountOption<'a>>>(
|
||||||
device: Arc<dyn BlockDevice>,
|
device: Arc<dyn BlockDevice>,
|
||||||
options: I,
|
options: I,
|
||||||
) -> Result<NodeRef, Error> {
|
) -> Result<NodeRef, Error> {
|
||||||
|
@ -158,7 +158,11 @@ impl IoContext {
|
|||||||
/// Makes a directory at given path become a "mountpoint" for the given filesystem root.
|
/// Makes a directory at given path become a "mountpoint" for the given filesystem root.
|
||||||
/// When accessed, the target directory will return contents of the filesystem root instead of
|
/// When accessed, the target directory will return contents of the filesystem root instead of
|
||||||
/// its own. Both the `target` path and `fs_root` Node must be directories.
|
/// its own. Both the `target` path and `fs_root` Node must be directories.
|
||||||
pub fn mount<P: AsRef<Path>>(&mut self, target: P, fs_root: NodeRef) -> Result<(), Error> {
|
pub fn mount<P: AsRef<Path>, F: FnOnce() -> Result<NodeRef, Error>>(
|
||||||
|
&mut self,
|
||||||
|
target: P,
|
||||||
|
create_fs: F,
|
||||||
|
) -> Result<(), Error> {
|
||||||
if !self.uid.is_root() {
|
if !self.uid.is_root() {
|
||||||
return Err(Error::PermissionDenied);
|
return Err(Error::PermissionDenied);
|
||||||
}
|
}
|
||||||
@ -169,7 +173,7 @@ impl IoContext {
|
|||||||
}
|
}
|
||||||
let target_node = self._find(self.root.clone(), target.trim_start_separators(), true)?;
|
let target_node = self._find(self.root.clone(), target.trim_start_separators(), true)?;
|
||||||
|
|
||||||
target_node.set_mountpoint_target(fs_root)
|
target_node.mount(create_fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Locates a [crate::Node] at given path and opens it with requested access options. If no
|
/// Locates a [crate::Node] at given path and opens it with requested access options. If no
|
||||||
|
@ -410,25 +410,24 @@ impl Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_mountpoint_target(self: &NodeRef, target: NodeRef) -> Result<(), Error> {
|
pub(crate) fn mount<F: FnOnce() -> Result<NodeRef, Error>>(
|
||||||
|
self: &NodeRef,
|
||||||
|
create_fs: F,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let directory = self.as_directory()?;
|
let directory = self.as_directory()?;
|
||||||
let mut mountpoint = directory.mountpoint.lock();
|
let mut mountpoint = directory.mountpoint.lock();
|
||||||
let mut target_parent_lock = target.parent.lock();
|
|
||||||
|
|
||||||
if mountpoint.is_some() {
|
if mountpoint.is_some() {
|
||||||
// TODO Busy
|
// TODO Busy
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
if target_parent_lock.is_some() {
|
|
||||||
// TODO mount a filesystem more than once?
|
|
||||||
return Err(Error::AlreadyExists);
|
|
||||||
}
|
|
||||||
if !target.is_directory() {
|
|
||||||
return Err(Error::NotADirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
mountpoint.replace(target.clone());
|
let fs_root = create_fs()?;
|
||||||
target_parent_lock.replace(self.clone());
|
let mut parent = fs_root.parent.lock();
|
||||||
|
assert!(fs_root.is_directory());
|
||||||
|
assert!(parent.is_none());
|
||||||
|
|
||||||
|
mountpoint.replace(fs_root.clone());
|
||||||
|
parent.replace(self.clone());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -436,7 +435,7 @@ impl Node {
|
|||||||
pub(crate) fn as_directory(&self) -> Result<&DirectoryData, Error> {
|
pub(crate) fn as_directory(&self) -> Result<&DirectoryData, Error> {
|
||||||
match &self.data {
|
match &self.data {
|
||||||
NodeImpl::Directory(dir) => Ok(dir),
|
NodeImpl::Directory(dir) => Ok(dir),
|
||||||
_ => Err(Error::InvalidFile),
|
_ => Err(Error::NotADirectory),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use ext2::Ext2Fs;
|
|||||||
use libk::{
|
use libk::{
|
||||||
block,
|
block,
|
||||||
fs::{devfs, sysfs},
|
fs::{devfs, sysfs},
|
||||||
vfs::{self, register_root, IoContext, NodeRef},
|
vfs::{self, register_root, FilesystemMountOption, IoContext, NodeRef},
|
||||||
};
|
};
|
||||||
use libk_mm::{
|
use libk_mm::{
|
||||||
address::{PhysicalAddress, Virtualize},
|
address::{PhysicalAddress, Virtualize},
|
||||||
@ -55,8 +55,8 @@ unsafe impl BlockAllocator for FileBlockAllocator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs an instance of a filesystem for given set of [MountOptions]
|
/// Mounts an instance of a filesystem for given set of [MountOptions].
|
||||||
pub fn create_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Result<NodeRef, Error> {
|
pub fn mount_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Result<(), Error> {
|
||||||
let Some(fs_name) = options.filesystem else {
|
let Some(fs_name) = options.filesystem else {
|
||||||
log::warn!("TODO: mount without filesystem type/fs probing not yet implemented");
|
log::warn!("TODO: mount without filesystem type/fs probing not yet implemented");
|
||||||
return Err(Error::NotImplemented);
|
return Err(Error::NotImplemented);
|
||||||
@ -69,8 +69,17 @@ pub fn create_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Resul
|
|||||||
}
|
}
|
||||||
ioctx.find(None, path, true)
|
ioctx.find(None, path, true)
|
||||||
});
|
});
|
||||||
|
let target = options.target;
|
||||||
let options = vfs::parse_mount_options(options.options);
|
let options = vfs::parse_mount_options(options.options);
|
||||||
|
|
||||||
|
ioctx.mount(target, move || create_filesystem(fs_name, source, options))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_filesystem<'a, I: IntoIterator<Item = FilesystemMountOption<'a>>>(
|
||||||
|
fs_name: &str,
|
||||||
|
source: Option<Result<NodeRef, Error>>,
|
||||||
|
options: I,
|
||||||
|
) -> Result<NodeRef, Error> {
|
||||||
let root = match fs_name {
|
let root = match fs_name {
|
||||||
"devfs" => devfs::root().clone(),
|
"devfs" => devfs::root().clone(),
|
||||||
"sysfs" => sysfs::root().clone(),
|
"sysfs" => sysfs::root().clone(),
|
||||||
@ -86,4 +95,3 @@ pub fn create_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Resul
|
|||||||
|
|
||||||
Ok(root)
|
Ok(root)
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
@ -47,9 +47,7 @@ pub(crate) fn mount(options: &MountOptions<'_>) -> Result<(), Error> {
|
|||||||
let process = thread.process();
|
let process = thread.process();
|
||||||
|
|
||||||
run_with_io(&process, |mut io| {
|
run_with_io(&process, |mut io| {
|
||||||
let fs_root = fs::create_filesystem(io.ioctx_mut(), options)?;
|
fs::mount_filesystem(io.ioctx_mut(), options)
|
||||||
io.ioctx_mut().mount(options.target, fs_root)?;
|
|
||||||
Ok(())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user