proc: add mount/unmount system calls
This commit is contained in:
parent
aa6b2ac469
commit
74cd9daed7
23
lib/vfs/src/debug.rs
Normal file
23
lib/vfs/src/debug.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use core::fmt;
|
||||
|
||||
pub(crate) static mut DEBUG_HOOK: Option<&'static dyn Fn(fmt::Arguments)> = None;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! debug_raw {
|
||||
($($arg:tt)+) => {
|
||||
$crate::debug::_debug_print(format_args!($($arg)+))
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! debugln {
|
||||
($($arg:tt)+) => {
|
||||
debug_raw!("[VFS] {}\n", format_args!($($arg)+))
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn _debug_print(args: fmt::Arguments) {
|
||||
if let Some(hook) = unsafe { DEBUG_HOOK.as_mut() } {
|
||||
hook(args);
|
||||
}
|
||||
}
|
@ -15,7 +15,13 @@ impl IoContext {
|
||||
}
|
||||
}
|
||||
|
||||
fn _find(&self, mut at: VnodeRef, path: &str, follow: bool) -> Result<VnodeRef, Error> {
|
||||
fn _find(
|
||||
&self,
|
||||
mut at: VnodeRef,
|
||||
path: &str,
|
||||
follow: bool,
|
||||
follow_mount: bool,
|
||||
) -> Result<VnodeRef, Error> {
|
||||
let mut element;
|
||||
let mut rest = path;
|
||||
|
||||
@ -35,18 +41,44 @@ impl IoContext {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO resolve link target
|
||||
if follow || follow_mount {
|
||||
while let Some(target) = at.target() {
|
||||
assert!(at.is_mountpoint());
|
||||
if at.is_mountpoint() && !follow_mount {
|
||||
break;
|
||||
}
|
||||
|
||||
debugln!("resolve parent: {:?} -> {:?}", at, target);
|
||||
at = target;
|
||||
}
|
||||
}
|
||||
|
||||
if !at.is_directory() {
|
||||
return Err(Error::NotADirectory);
|
||||
}
|
||||
|
||||
if element.is_empty() && rest.is_empty() {
|
||||
return Ok(at);
|
||||
}
|
||||
|
||||
let node = at.lookup_or_load(element)?;
|
||||
let mut node = at.lookup_or_load(element)?;
|
||||
|
||||
if follow || follow_mount {
|
||||
while let Some(target) = node.target() {
|
||||
assert!(node.is_mountpoint());
|
||||
if node.is_mountpoint() && !follow_mount {
|
||||
break;
|
||||
}
|
||||
|
||||
debugln!("resolve node: {:?} -> {:?}", node, target);
|
||||
node = target;
|
||||
}
|
||||
}
|
||||
|
||||
if rest.is_empty() {
|
||||
Ok(node)
|
||||
} else {
|
||||
self._find(node, rest, follow)
|
||||
self._find(node, rest, follow, follow_mount)
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +87,10 @@ impl IoContext {
|
||||
at: Option<VnodeRef>,
|
||||
mut path: &str,
|
||||
follow: bool,
|
||||
follow_mount: bool,
|
||||
) -> Result<VnodeRef, Error> {
|
||||
debugln!("_find {:?} in {:?}", path, at);
|
||||
|
||||
let at = if path.starts_with('/') {
|
||||
path = path.trim_start_matches('/');
|
||||
self.root.clone()
|
||||
@ -65,7 +100,7 @@ impl IoContext {
|
||||
self.cwd.clone()
|
||||
};
|
||||
|
||||
self._find(at, path, follow)
|
||||
self._find(at, path, follow, follow_mount)
|
||||
}
|
||||
|
||||
pub fn open(
|
||||
@ -74,7 +109,7 @@ impl IoContext {
|
||||
path: &str,
|
||||
opts: OpenFlags,
|
||||
) -> Result<FileRef, Error> {
|
||||
let node = match self.find(at.clone(), path, true) {
|
||||
let node = match self.find(at.clone(), path, true, true) {
|
||||
Err(Error::DoesNotExist) => {
|
||||
// TODO check for create option
|
||||
return Err(Error::DoesNotExist);
|
||||
@ -84,11 +119,15 @@ impl IoContext {
|
||||
|
||||
node.open(opts)
|
||||
}
|
||||
|
||||
pub fn root(&self) -> &VnodeRef {
|
||||
&self.root
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use abi::error::Error;
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
use crate::{node::VnodeRef, IoContext};
|
||||
use std::fmt;
|
||||
@ -115,7 +154,7 @@ mod tests {
|
||||
|
||||
impl fmt::Debug for DumpNode<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.node.dump(f, 0)
|
||||
self.node.dump(f, 0, true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,79 +176,93 @@ mod tests {
|
||||
|
||||
// Absolute lookups
|
||||
assert_eq!(
|
||||
ctx.find(None, "/file1.txt", false).unwrap().name(),
|
||||
ctx.find(None, "/file1.txt", false, false).unwrap().name(),
|
||||
"file1.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(None, "/file3.txt", false).unwrap_err(),
|
||||
ctx.find(None, "/file3.txt", false, false).unwrap_err(),
|
||||
Error::DoesNotExist
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(None, "/dir1/file3.txt", false).unwrap().name(),
|
||||
ctx.find(None, "/dir1/file3.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file3.txt"
|
||||
);
|
||||
|
||||
// Non-absolute lookups from root
|
||||
assert_eq!(
|
||||
ctx.find(None, "file1.txt", false).unwrap().name(),
|
||||
ctx.find(None, "file1.txt", false, false).unwrap().name(),
|
||||
"file1.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(None, "dir1/file3.txt", false).unwrap().name(),
|
||||
ctx.find(None, "dir1/file3.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file3.txt"
|
||||
);
|
||||
|
||||
// Absolute lookups from non-root
|
||||
let cwd = ctx.find(None, "/dir1", false).unwrap();
|
||||
let cwd = ctx.find(None, "/dir1", false, false).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "/file1.txt", false)
|
||||
ctx.find(Some(cwd.clone()), "/file1.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file1.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "/dir1/file3.txt", false)
|
||||
ctx.find(Some(cwd.clone()), "/dir1/file3.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file3.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "/file3.txt", false)
|
||||
ctx.find(Some(cwd.clone()), "/file3.txt", false, false)
|
||||
.unwrap_err(),
|
||||
Error::DoesNotExist
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "/dir2", false).unwrap_err(),
|
||||
ctx.find(Some(cwd.clone()), "/dir2", false, false)
|
||||
.unwrap_err(),
|
||||
Error::DoesNotExist
|
||||
);
|
||||
|
||||
// Non-absolute lookups in non-root
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "file3.txt", false)
|
||||
ctx.find(Some(cwd.clone()), "file3.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file3.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "././file3.txt", false)
|
||||
ctx.find(Some(cwd.clone()), "././file3.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file3.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "../dir1/file3.txt", false)
|
||||
ctx.find(Some(cwd.clone()), "../dir1/file3.txt", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"file3.txt"
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), ".", false).unwrap().name(),
|
||||
ctx.find(Some(cwd.clone()), ".", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
"dir1"
|
||||
);
|
||||
assert_eq!(ctx.find(Some(cwd.clone()), "..", false).unwrap().name(), "");
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "../..", false).unwrap().name(),
|
||||
ctx.find(Some(cwd.clone()), "..", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
""
|
||||
);
|
||||
assert_eq!(
|
||||
ctx.find(Some(cwd.clone()), "../..", false, false)
|
||||
.unwrap()
|
||||
.name(),
|
||||
""
|
||||
);
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ extern crate alloc;
|
||||
#[cfg(test)]
|
||||
extern crate std;
|
||||
|
||||
#[macro_use]
|
||||
pub(crate) mod debug;
|
||||
|
||||
pub(crate) mod block;
|
||||
pub(crate) mod char;
|
||||
pub(crate) mod file;
|
||||
@ -62,3 +65,7 @@ fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Res
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn init_debug_hook(hook: &'static dyn Fn(core::fmt::Arguments)) {
|
||||
debug::DEBUG_HOOK.replace(hook);
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ pub struct Vnode {
|
||||
kind: VnodeKind,
|
||||
data: RefCell<Option<Box<dyn VnodeImpl>>>,
|
||||
fs: RefCell<Option<Rc<dyn Filesystem>>>,
|
||||
target: RefCell<Option<VnodeRef>>,
|
||||
}
|
||||
|
||||
pub trait VnodeImpl {
|
||||
@ -69,6 +70,7 @@ impl Vnode {
|
||||
kind,
|
||||
data: RefCell::new(None),
|
||||
fs: RefCell::new(None),
|
||||
target: RefCell::new(None),
|
||||
})
|
||||
}
|
||||
|
||||
@ -82,6 +84,11 @@ impl Vnode {
|
||||
self.kind
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn target(&self) -> Option<VnodeRef> {
|
||||
self.target.borrow().clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn data(&self) -> RefMut<Option<Box<dyn VnodeImpl>>> {
|
||||
self.data.borrow_mut()
|
||||
@ -92,6 +99,11 @@ impl Vnode {
|
||||
self.fs.borrow().clone()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_target(&self, target: Option<VnodeRef>) {
|
||||
self.target.replace(target);
|
||||
}
|
||||
|
||||
pub fn parent(self: &VnodeRef) -> VnodeRef {
|
||||
match &self.tree.borrow().parent {
|
||||
Some(parent) => parent.upgrade().unwrap(),
|
||||
@ -112,6 +124,11 @@ impl Vnode {
|
||||
self.kind == VnodeKind::Directory
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_mountpoint(&self) -> bool {
|
||||
self.is_directory() && self.target.borrow().is_some()
|
||||
}
|
||||
|
||||
// Cache tree operations
|
||||
pub fn add_child(self: &VnodeRef, child: VnodeRef) {
|
||||
let parent_weak = Rc::downgrade(self);
|
||||
@ -126,22 +143,32 @@ impl Vnode {
|
||||
parent_borrow.children.push(child);
|
||||
}
|
||||
|
||||
pub fn dump(&self, f: &mut fmt::Formatter<'_>, depth: usize) -> fmt::Result {
|
||||
pub fn dump(&self, f: &mut fmt::Formatter<'_>, depth: usize, indent: bool) -> fmt::Result {
|
||||
if indent {
|
||||
for _ in 0..depth {
|
||||
f.write_str(" ")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "{:?}", self.name)?;
|
||||
|
||||
match self.kind {
|
||||
VnodeKind::Directory => {
|
||||
let tree = self.tree.borrow();
|
||||
let target = self.target();
|
||||
|
||||
if let Some(target) = target {
|
||||
assert_eq!(tree.children.len(), 0);
|
||||
f.write_str(" -> ")?;
|
||||
return target.dump(f, depth, false);
|
||||
}
|
||||
|
||||
if tree.children.is_empty() {
|
||||
f.write_str(" []")?;
|
||||
} else {
|
||||
f.write_str(" [\n")?;
|
||||
for child in tree.children.iter() {
|
||||
child.dump(f, depth + 1)?;
|
||||
child.dump(f, depth + 1, true)?;
|
||||
f.write_str("\n")?;
|
||||
}
|
||||
for _ in 0..depth {
|
||||
@ -265,6 +292,48 @@ impl Vnode {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mount(self: &VnodeRef, fs_root: VnodeRef) -> Result<(), Error> {
|
||||
if !self.is_directory() {
|
||||
return Err(Error::NotADirectory);
|
||||
}
|
||||
if !fs_root.is_directory() {
|
||||
todo!("Filesystem root is not a directory");
|
||||
}
|
||||
if self.target.borrow().is_some() {
|
||||
todo!("Target mountpoint is busy");
|
||||
}
|
||||
|
||||
{
|
||||
let mut child_borrow = fs_root.tree.borrow_mut();
|
||||
if child_borrow.parent.is_some() {
|
||||
todo!("Filesystem is already mounted somewhere else");
|
||||
}
|
||||
child_borrow.parent = Some(Rc::downgrade(self));
|
||||
}
|
||||
self.target.replace(Some(fs_root));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unmount_target(self: &VnodeRef) -> Result<(), Error> {
|
||||
if !self.is_directory() {
|
||||
return Err(Error::NotADirectory);
|
||||
}
|
||||
let Some(fs_root) = self.target.take() else {
|
||||
todo!();
|
||||
};
|
||||
|
||||
{
|
||||
let mut target_borrow = fs_root.tree.borrow_mut();
|
||||
let Some(parent) = target_borrow.parent.take() else {
|
||||
todo!()
|
||||
};
|
||||
assert!(Rc::ptr_eq(self, &parent.upgrade().unwrap()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Vnode {
|
||||
@ -288,6 +357,6 @@ impl VnodeDump {
|
||||
|
||||
impl fmt::Debug for VnodeDump {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.node.dump(f, 0)
|
||||
self.node.dump(f, 0, true)
|
||||
}
|
||||
}
|
||||
|
@ -128,6 +128,11 @@ pub fn init() {
|
||||
DEBUG_PRINTER.init(IrqSafeSpinlock::new(DebugPrinter {
|
||||
sink: PLATFORM.primary_serial().unwrap(),
|
||||
}));
|
||||
unsafe {
|
||||
vfs::init_debug_hook(&move |args| {
|
||||
debug_internal(args, LogLevel::Debug);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[doc = "hide"]
|
||||
|
@ -1,7 +1,13 @@
|
||||
//! Filesystem implementations
|
||||
|
||||
use vfs::VnodeRef;
|
||||
use yggdrasil_abi::{error::Error, io::MountOptions};
|
||||
|
||||
use crate::util::OneTimeInit;
|
||||
|
||||
pub mod devfs;
|
||||
pub mod tar;
|
||||
|
||||
pub struct Initrd {
|
||||
pub phys_page_start: usize,
|
||||
pub phys_page_len: usize,
|
||||
@ -10,5 +16,11 @@ pub struct Initrd {
|
||||
|
||||
pub static INITRD_DATA: OneTimeInit<Initrd> = OneTimeInit::new();
|
||||
|
||||
pub mod devfs;
|
||||
pub mod tar;
|
||||
pub fn create_filesystem(options: &MountOptions) -> Result<VnodeRef, Error> {
|
||||
let fs_name = options.filesystem.unwrap();
|
||||
|
||||
match fs_name {
|
||||
"devfs" => Ok(devfs::root().clone()),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
29
src/main.rs
29
src/main.rs
@ -15,8 +15,6 @@
|
||||
|
||||
extern crate yggdrasil_abi as abi;
|
||||
|
||||
use core::ops::DerefMut;
|
||||
|
||||
use abi::{
|
||||
error::Error,
|
||||
io::{OpenFlags, RawFd},
|
||||
@ -67,7 +65,7 @@ pub fn kernel_main() {
|
||||
let tty_node = devfs_root.lookup("ttyS0").unwrap();
|
||||
|
||||
let ioctx = IoContext::new(root);
|
||||
let node = ioctx.find(None, "/init", false).unwrap();
|
||||
let node = ioctx.find(None, "/init", true, true).unwrap();
|
||||
let file = node.open(OpenFlags::new().read()).unwrap();
|
||||
|
||||
{
|
||||
@ -83,30 +81,5 @@ pub fn kernel_main() {
|
||||
user_init.enqueue_somewhere();
|
||||
}
|
||||
|
||||
// static USER_PROGRAM: &[u8] = include_bytes!(concat!(
|
||||
// "../../target/aarch64-unknown-yggdrasil/",
|
||||
// env!("PROFILE"),
|
||||
// "/test_program"
|
||||
// ));
|
||||
|
||||
// let ioctx = IoContext::new(devfs_root.clone());
|
||||
|
||||
// // Spawn a test user task
|
||||
// let proc =
|
||||
// proc::exec::create_from_memory(USER_PROGRAM, &["user-program", "argument 1", "argument 2"]);
|
||||
|
||||
// match proc {
|
||||
// Ok(proc) => {
|
||||
// // Setup I/O for the process
|
||||
// // let mut io = proc.io.lock();
|
||||
// // io.set_file(RawFd::STDOUT, todo!()).unwrap();
|
||||
|
||||
// proc.enqueue_somewhere();
|
||||
// }
|
||||
// Err(err) => {
|
||||
// warnln!("Failed to create user process: {:?}", err);
|
||||
// }
|
||||
// };
|
||||
|
||||
Process::current().exit(0);
|
||||
}
|
||||
|
@ -53,12 +53,12 @@ impl PhysicalMemoryRegion {
|
||||
}
|
||||
|
||||
/// Returns an address range covered by the region
|
||||
pub const fn range(&self) -> Range<usize> {
|
||||
pub fn range(&self) -> Range<usize> {
|
||||
self.base..self.end()
|
||||
}
|
||||
|
||||
/// Provides an iterator over the pages in the region
|
||||
pub const fn pages(&self) -> StepBy<Range<usize>> {
|
||||
pub fn pages(&self) -> StepBy<Range<usize>> {
|
||||
self.range().step_by(0x1000)
|
||||
}
|
||||
}
|
||||
|
32
src/syscall/arg.rs
Normal file
32
src/syscall/arg.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use core::alloc::Layout;
|
||||
|
||||
use yggdrasil_abi::error::Error;
|
||||
|
||||
pub(super) fn arg_buffer_ref<'a>(base: usize, len: usize) -> Result<&'a [u8], Error> {
|
||||
if base + len > crate::mem::KERNEL_VIRT_OFFSET {
|
||||
panic!("Invalid argument");
|
||||
}
|
||||
Ok(unsafe { core::slice::from_raw_parts(base as *const u8, len) })
|
||||
}
|
||||
|
||||
pub(super) fn arg_buffer_mut<'a>(base: usize, len: usize) -> Result<&'a mut [u8], Error> {
|
||||
if base + len > crate::mem::KERNEL_VIRT_OFFSET {
|
||||
panic!("Invalid argument");
|
||||
}
|
||||
Ok(unsafe { core::slice::from_raw_parts_mut(base as *mut u8, len) })
|
||||
}
|
||||
|
||||
pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
|
||||
let slice = arg_buffer_ref(base, len)?;
|
||||
Ok(core::str::from_utf8(slice).unwrap())
|
||||
}
|
||||
|
||||
pub(super) fn arg_user_ref<'a, T: Sized>(addr: usize) -> Result<&'a T, Error> {
|
||||
let layout = Layout::new::<T>();
|
||||
if addr % layout.align() != 0 {
|
||||
todo!("Misaligned argument");
|
||||
}
|
||||
// TODO check that addr actually points to mapped (and user-accessible) memory
|
||||
let value = unsafe { core::mem::transmute::<_, &'a T>(addr) };
|
||||
Ok(value)
|
||||
}
|
@ -7,31 +7,17 @@ use abi::{
|
||||
syscall::SyscallFunction,
|
||||
};
|
||||
use vfs::{Read, Write};
|
||||
use yggdrasil_abi::io::{MountOptions, UnmountOptions};
|
||||
|
||||
use crate::{
|
||||
fs,
|
||||
mem::table::{PageAttributes, VirtualMemoryManager},
|
||||
proc::wait,
|
||||
task::process::Process,
|
||||
};
|
||||
|
||||
fn arg_buffer_ref<'a>(base: usize, len: usize) -> Result<&'a [u8], Error> {
|
||||
if base + len > crate::mem::KERNEL_VIRT_OFFSET {
|
||||
panic!("Invalid argument");
|
||||
}
|
||||
Ok(unsafe { core::slice::from_raw_parts(base as *const u8, len) })
|
||||
}
|
||||
|
||||
fn arg_buffer_mut<'a>(base: usize, len: usize) -> Result<&'a mut [u8], Error> {
|
||||
if base + len > crate::mem::KERNEL_VIRT_OFFSET {
|
||||
panic!("Invalid argument");
|
||||
}
|
||||
Ok(unsafe { core::slice::from_raw_parts_mut(base as *mut u8, len) })
|
||||
}
|
||||
|
||||
fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error> {
|
||||
let slice = arg_buffer_ref(base, len)?;
|
||||
Ok(core::str::from_utf8(slice).unwrap())
|
||||
}
|
||||
mod arg;
|
||||
use arg::*;
|
||||
|
||||
fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error> {
|
||||
match func {
|
||||
@ -132,6 +118,38 @@ fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result<usize, Error>
|
||||
io.close_file(fd)?;
|
||||
Ok(0)
|
||||
}
|
||||
SyscallFunction::Mount => {
|
||||
let options = arg_user_ref::<MountOptions>(args[0] as usize)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let target_node = io.ioctx().find(None, options.target, true, false)?;
|
||||
if !target_node.is_directory() {
|
||||
return Err(Error::NotADirectory);
|
||||
}
|
||||
|
||||
let fs_root = fs::create_filesystem(options)?;
|
||||
|
||||
target_node.mount(fs_root)?;
|
||||
|
||||
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
SyscallFunction::Unmount => {
|
||||
let options = arg_user_ref::<UnmountOptions>(args[0] as usize)?;
|
||||
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
|
||||
let mountpoint = io.ioctx().find(None, options.mountpoint, true, false)?;
|
||||
mountpoint.unmount_target()?;
|
||||
|
||||
debugln!("{:?}", vfs::VnodeDump::new(io.ioctx().root().clone()));
|
||||
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user