From df01446e21448e8d48fa5a1ed827c3f6d1777468 Mon Sep 17 00:00:00 2001 From: juls0730 <62722391+juls0730@users.noreply.github.com> Date: Sat, 25 May 2024 15:03:11 -0500 Subject: [PATCH] add unmounting vfs --- src/drivers/fs/vfs.rs | 126 ++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 53 +++++++++++------- 2 files changed, 152 insertions(+), 27 deletions(-) diff --git a/src/drivers/fs/vfs.rs b/src/drivers/fs/vfs.rs index 777bec5..88d099a 100755 --- a/src/drivers/fs/vfs.rs +++ b/src/drivers/fs/vfs.rs @@ -3,7 +3,6 @@ use core::{fmt::Debug, ptr::NonNull}; use alloc::{ boxed::Box, collections::BTreeMap, - rc::Rc, string::{String, ToString}, sync::Arc, vec::Vec, @@ -17,6 +16,7 @@ static mut ROOT_VFS: Vfs = Vfs::null(); // TODO: everything being Option to accomodate the stupid null root vfs is getting annoying #[allow(unused)] pub struct Vfs { + mount_point: Option, next: Option>, pub fs: Option>, vnode_covered: Option>, @@ -29,7 +29,8 @@ impl !Sync for Vfs {} impl Vfs { const fn null() -> Self { - return Vfs { + return Self { + mount_point: None, next: None, fs: None, vnode_covered: None, @@ -39,11 +40,53 @@ impl Vfs { }; } + fn new(fs: Box, mount_point: &str) -> Self { + return Self { + mount_point: Some(mount_point.to_string()), + next: None, + fs: Some(fs), + vnode_covered: None, + flags: 0, + block_size: 0, + data: core::ptr::null_mut(), + }; + } + + // sketchy and dumb? yes, but it works + fn prev(&self) -> Option<&mut Box> { + let mut cur_vfs = unsafe { ROOT_VFS.next.as_mut() }; + while let Some(vfs) = cur_vfs { + if let Some(next_vfs) = &vfs.next { + if next_vfs.mount_point == self.mount_point { + return Some(vfs); + } + } + + cur_vfs = vfs.next.as_mut(); + } + + None + } + + fn del_vfs(&mut self, target_name: &str) { + let mut curr = self.next.as_mut(); + + while let Some(node) = curr { + if node.mount_point.as_deref() == Some(target_name) { + node.prev().unwrap().next = node.next.take(); + return; + } + + curr = node.next.as_mut(); + } + } + fn add_vfs(&mut self, vfs: Box) { let mut current = self; while let Some(ref mut next_vfs) = current.next { current = next_vfs; } + current.next = Some(vfs); } @@ -189,7 +232,11 @@ impl File { unsafe { self.descriptor.as_mut() } } - pub fn read(&mut self, count: usize, offset: usize, f: u32) -> Result, ()> { + pub fn read(&mut self, mut count: usize, offset: usize, f: u32) -> Result, ()> { + if count == 0 { + count = self.len() - offset; + } + return self.get_node().read(count, offset, f); } @@ -618,9 +665,7 @@ pub struct VAttr { pub fn add_vfs(mount_point: &str, fs_ops: Box) -> Result<(), ()> { // Initialize the data so we can use the nonnull helpers - let mut new_vfs = Vfs::null(); - new_vfs.fs = Some(fs_ops); - let mut vfs = Box::new(new_vfs); + let mut vfs = Box::new(Vfs::new(fs_ops, mount_point)); let vfsp = vfs.as_ptr(); @@ -655,6 +700,75 @@ pub fn add_vfs(mount_point: &str, fs_ops: Box) -> Result<(), ()> { return Ok(()); } +// returns if the path in other_mount_point starts with mount_point but more sophisticated-ly +fn mount_point_busy(mount_point: &str) -> bool { + let mount_parts = mount_point + .split_terminator('/') + .filter(|x| !x.is_empty()) + .collect::>(); + let mut next_vfs = unsafe { ROOT_VFS.next.as_ref() }; + + while let Some(vfs) = next_vfs { + if vfs.mount_point.as_ref().unwrap() == mount_point { + // dont consider ourself as a user of ourself + next_vfs = vfs.next.as_ref(); + continue; + } + + let parts = vfs + .mount_point + .as_ref() + .unwrap() + .split_terminator('/') + .filter(|x| !x.is_empty()) + .collect::>(); + + for (i, &part) in parts.iter().enumerate() { + if i > mount_parts.len() - 1 { + return true; + } + + if part == mount_parts[i] { + continue; + } else { + break; + } + } + + next_vfs = vfs.next.as_ref(); + } + + return false; +} + +pub fn del_vfs(mount_point: &str) -> Result<(), ()> { + if unsafe { ROOT_VFS.next.is_none() } { + return Err(()); + } + + log_info!("Deleting vfs at {mount_point}"); + + if mount_point == "/" { + if unsafe { ROOT_VFS.next.as_ref().unwrap().next.is_some() } { + // mount point is 'busy' + return Err(()); + } + + unsafe { ROOT_VFS.next = None }; + } else { + if mount_point_busy(mount_point) { + crate::println!("busy"); + return Err(()); + } + + crate::println!("Deleting VFS"); + + unsafe { ROOT_VFS.del_vfs(mount_point) }; + } + + return Ok(()); +} + pub fn vfs_open(path: &str) -> Result<&mut TreeNode, ()> { if unsafe { ROOT_VFS.next.is_none() || NODE_TREE.is_none() } { return Err(()); diff --git a/src/main.rs b/src/main.rs index da8734b..bda831d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,32 +51,31 @@ pub fn kmain() -> ! { #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] drivers::pci::enumerate_pci_bus(); - let mut file = vfs_open("/firstdir/seconddirbutlonger/yeah.txt") - .unwrap() - .open(0, UserCred { uid: 0, gid: 0 }); - - let file_len = file.len(); - - crate::println!("YEAH.TXT: {:X?}", file.read(file_len, 0, 0)); + crate::println!( + "YEAH.TXT: {:X?}", + vfs_open("/firstdir/seconddirbutlonger/yeah.txt") + .unwrap() + .open(0, UserCred { uid: 0, gid: 0 }) + .read(0, 0, 0) + ); drivers::storage::ide::init(); let limine_dir = vfs_open("/mnt/boot/limine").unwrap(); - crate::println!("LIMINE BOOT: {:X?}", { - let mut cfg_file = limine_dir + crate::println!( + "LIMINE BOOT: {:X?}", + limine_dir .lookup("limine.cfg") .unwrap() - .open(0, UserCred { uid: 0, gid: 0 }); - - let len = cfg_file.len(); - - cfg_file.read(len, 0, 0) - }); + .open(0, UserCred { uid: 0, gid: 0 }) + .read(0, 0, 0) + ); let root_dir = vfs_open("/").unwrap(); - crate::println!("LIMINE BOOT THROUGH LOOKUP: {:X?}", { - let mut cfg_file = root_dir + crate::println!( + "LIMINE BOOT THROUGH LOOKUP: {:X?}", + root_dir .lookup("mnt") .unwrap() .lookup("boot") @@ -85,12 +84,24 @@ pub fn kmain() -> ! { .unwrap() .lookup("limine.cfg") .unwrap() - .open(0, UserCred { uid: 0, gid: 0 }); + .open(0, UserCred { uid: 0, gid: 0 }) + .read(0, 10, 0) + ); - let len = cfg_file.len(); + let _ = drivers::fs::vfs::del_vfs("/mnt"); - cfg_file.read(len, 0, 0) - }); + println!("wa"); + + let limine_dir = vfs_open("/mnt/boot/limine").unwrap(); + + crate::println!( + "LIMINE BOOT: {:X?}", + limine_dir + .lookup("limine.cfg") + .unwrap() + .open(0, UserCred { uid: 0, gid: 0 }) + .read(0, 0, 0) + ); // let file = vfs_open("/example.txt").unwrap();