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 {
|
||||
pub async fn create<'a, I: Iterator<Item = FilesystemMountOption<'a>>>(
|
||||
pub async fn create<'a, I: IntoIterator<Item = FilesystemMountOption<'a>>>(
|
||||
device: Arc<dyn BlockDevice>,
|
||||
options: I,
|
||||
) -> Result<NodeRef, Error> {
|
||||
|
@ -158,7 +158,11 @@ impl IoContext {
|
||||
/// 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
|
||||
/// 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() {
|
||||
return Err(Error::PermissionDenied);
|
||||
}
|
||||
@ -169,7 +173,7 @@ impl IoContext {
|
||||
}
|
||||
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
|
||||
|
@ -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 mut mountpoint = directory.mountpoint.lock();
|
||||
let mut target_parent_lock = target.parent.lock();
|
||||
|
||||
if mountpoint.is_some() {
|
||||
// TODO Busy
|
||||
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());
|
||||
target_parent_lock.replace(self.clone());
|
||||
let fs_root = create_fs()?;
|
||||
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(())
|
||||
}
|
||||
@ -436,7 +435,7 @@ impl Node {
|
||||
pub(crate) fn as_directory(&self) -> Result<&DirectoryData, Error> {
|
||||
match &self.data {
|
||||
NodeImpl::Directory(dir) => Ok(dir),
|
||||
_ => Err(Error::InvalidFile),
|
||||
_ => Err(Error::NotADirectory),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ use ext2::Ext2Fs;
|
||||
use libk::{
|
||||
block,
|
||||
fs::{devfs, sysfs},
|
||||
vfs::{self, register_root, IoContext, NodeRef},
|
||||
vfs::{self, register_root, FilesystemMountOption, IoContext, NodeRef},
|
||||
};
|
||||
use libk_mm::{
|
||||
address::{PhysicalAddress, Virtualize},
|
||||
@ -55,8 +55,8 @@ unsafe impl BlockAllocator for FileBlockAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an instance of a filesystem for given set of [MountOptions]
|
||||
pub fn create_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Result<NodeRef, Error> {
|
||||
/// Mounts an instance of a filesystem for given set of [MountOptions].
|
||||
pub fn mount_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Result<(), Error> {
|
||||
let Some(fs_name) = options.filesystem else {
|
||||
log::warn!("TODO: mount without filesystem type/fs probing not yet implemented");
|
||||
return Err(Error::NotImplemented);
|
||||
@ -69,8 +69,17 @@ pub fn create_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Resul
|
||||
}
|
||||
ioctx.find(None, path, true)
|
||||
});
|
||||
|
||||
let target = options.target;
|
||||
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 {
|
||||
"devfs" => devfs::root().clone(),
|
||||
"sysfs" => sysfs::root().clone(),
|
||||
@ -86,4 +95,3 @@ pub fn create_filesystem(ioctx: &mut IoContext, options: &MountOptions) -> Resul
|
||||
|
||||
Ok(root)
|
||||
}
|
||||
// }
|
||||
|
@ -47,9 +47,7 @@ pub(crate) fn mount(options: &MountOptions<'_>) -> Result<(), Error> {
|
||||
let process = thread.process();
|
||||
|
||||
run_with_io(&process, |mut io| {
|
||||
let fs_root = fs::create_filesystem(io.ioctx_mut(), options)?;
|
||||
io.ioctx_mut().mount(options.target, fs_root)?;
|
||||
Ok(())
|
||||
fs::mount_filesystem(io.ioctx_mut(), options)
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user