From 3bcaf5cf16a43f60137e7bf96209c9d401a44e66 Mon Sep 17 00:00:00 2001 From: Eemeli Lehtonen <eemeli.o.lehtonen@utu.fi> Date: Mon, 22 May 2023 16:57:27 +0300 Subject: [PATCH] fix: vfs infinite recurse --- src/driver/acpi/hpet.rs | 10 +++--- src/driver/rtc.rs | 12 +++---- src/main.rs | 5 +-- src/mem/pmm.rs | 2 -- src/mem/slab.rs | 1 + src/scheduler/kshell/shell.rs | 11 +++--- src/util/slice_read.rs | 52 +++++++++------------------ src/vfs/devices.rs | 8 +++-- src/vfs/mod.rs | 67 +++++++++-------------------------- 9 files changed, 59 insertions(+), 109 deletions(-) diff --git a/src/driver/acpi/hpet.rs b/src/driver/acpi/hpet.rs index 5dbf8a0..79381ef 100644 --- a/src/driver/acpi/hpet.rs +++ b/src/driver/acpi/hpet.rs @@ -10,7 +10,8 @@ use spin::{Lazy, Mutex}; use crate::{ debug, trace, - vfs::{FileDevice, IoResult}, + util::slice_read::{self, slice_read, slice_write}, + vfs::{FileDevice, IoError, IoResult}, }; use super::{rsdt::RSDT, SdtError}; @@ -234,12 +235,11 @@ impl FileDevice for HpetDevice { fn read(&self, offset: usize, buf: &mut [u8]) -> IoResult<usize> { let bytes = &HPET.lock().now_bytes()[..]; - bytes.read(offset, buf) + slice_read(bytes, offset, buf) } - fn write(&mut self, offset: usize, buf: &[u8]) -> IoResult<usize> { - let mut bytes = &HPET.lock().now_bytes()[..]; - bytes.write(offset, buf) + fn write(&mut self, _: usize, _: &[u8]) -> IoResult<usize> { + Err(IoError::PermissionDenied) } } diff --git a/src/driver/rtc.rs b/src/driver/rtc.rs index 5bd0d56..becbb1a 100644 --- a/src/driver/rtc.rs +++ b/src/driver/rtc.rs @@ -1,6 +1,7 @@ use crate::{ debug, error, - vfs::{self, FileDevice}, + util::slice_read::slice_read, + vfs::{self, FileDevice, IoError, IoResult}, }; use chrono::{DateTime, TimeZone, Utc}; use core::{ @@ -110,14 +111,13 @@ impl FileDevice for RtcDevice { mem::size_of::<i64>() } - fn read(&self, offset: usize, buf: &mut [u8]) -> vfs::IoResult<usize> { + fn read(&self, offset: usize, buf: &mut [u8]) -> IoResult<usize> { let bytes = &RTC.now_bytes()[..]; - bytes.read(offset, buf) + slice_read(bytes, offset, buf) } - fn write(&mut self, offset: usize, buf: &[u8]) -> vfs::IoResult<usize> { - let mut bytes = &RTC.now_bytes()[..]; - bytes.write(offset, buf) + fn write(&mut self, _: usize, _: &[u8]) -> IoResult<usize> { + Err(IoError::PermissionDenied) } } diff --git a/src/main.rs b/src/main.rs index fd91494..f5fa755 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,14 +24,15 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use crate::{ - arch::cpu::idt::Irq, + arch::{cpu::idt::Irq, int}, driver::{ acpi::{apic::ApicId, ioapic::IoApic}, - rtc, + rtc::{self, RtcDevice, RTC}, }, scheduler::kshell::kshell, smp::CPU_COUNT, util::fmt::NumberPostfix, + vfs::FileDevice, }; extern crate alloc; diff --git a/src/mem/pmm.rs b/src/mem/pmm.rs index c1125ac..3b90688 100755 --- a/src/mem/pmm.rs +++ b/src/mem/pmm.rs @@ -131,8 +131,6 @@ impl PageFrameAllocator { self.used .fetch_add(count as u64 * PAGE_SIZE, Ordering::SeqCst); - // trace!("allocating pages first={first_page} count={}", count); - PageFrame { first: addr, count } } diff --git a/src/mem/slab.rs b/src/mem/slab.rs index 7620c48..6575917 100644 --- a/src/mem/slab.rs +++ b/src/mem/slab.rs @@ -90,6 +90,7 @@ impl SlabAllocator { } pub fn alloc(&self, size: usize) -> VirtAddr { + // crate::println!("alloc {size}"); if let Some(slab) = self.get_slab(size) { slab.write().alloc(&self.stats) } else { diff --git a/src/scheduler/kshell/shell.rs b/src/scheduler/kshell/shell.rs index 34f8360..c72b36d 100644 --- a/src/scheduler/kshell/shell.rs +++ b/src/scheduler/kshell/shell.rs @@ -1,6 +1,6 @@ use crate::{ driver::acpi::hpet::HPET, - mem::pmm::PageFrameAllocator, + mem::{from_higher_half, pmm::PageFrameAllocator}, util::fmt::NumberPostfix, vfs::{ self, @@ -13,7 +13,8 @@ use alloc::{borrow::ToOwned, string::String, sync::Arc}; use chrono::{TimeZone, Utc}; use core::fmt::Write; use snafu::ResultExt; -use spin::Mutex; +use spin::{Mutex, MutexGuard}; +use x86_64::VirtAddr; use super::{term::Term, Error, IoSnafu, Result}; @@ -103,7 +104,7 @@ impl<'fbo> Shell<'fbo> { } fn splash_cmd(&mut self, _: Option<&str>) -> Result<()> { - _ = writeln!(self.term, "{KERNEL_SPLASH}"); + // _ = writeln!(self.term, "{KERNEL_SPLASH}"); _ = writeln!(self.term, "Welcome to {KERNEL_NAME} - {KERNEL_VERSION} (built {KERNEL_BUILD_TIME} build [{KERNEL_BUILD_REV}])"); Ok(()) } @@ -156,14 +157,16 @@ impl<'fbo> Shell<'fbo> { let file = vfs::get_file(resource, false, false).with_context(|_| IoSnafu { resource: resource.to_owned(), })?; - let mut file = file.lock(); + let file = file.lock(); let mut at = 0usize; let mut buf = [0u8; 16]; loop { + let addr = (&*file) as *const _ as *const () as u64; let read = file.read(at, &mut buf).with_context(|_| IoSnafu { resource: resource.to_owned(), })?; + if read == 0 { break; } diff --git a/src/util/slice_read.rs b/src/util/slice_read.rs index 64bfaef..37d8a5f 100644 --- a/src/util/slice_read.rs +++ b/src/util/slice_read.rs @@ -2,46 +2,26 @@ use crate::vfs::{FileDevice, IoError, IoResult}; // -impl FileDevice for &'_ [u8] { - fn len(&self) -> usize { - self.len() - } +pub fn slice_read(this: &[u8], offset: usize, buf: &mut [u8]) -> IoResult<usize> { + let len = this + .len() + .checked_sub(offset) + .ok_or(IoError::UnexpectedEOF)? + .min(buf.len()); - fn read(&self, offset: usize, buf: &mut [u8]) -> IoResult<usize> { - let len = self - .len() - .checked_sub(offset) - .ok_or(IoError::UnexpectedEOF)? - .min(buf.len()); + buf[..len].copy_from_slice(&this[offset..offset + len]); - buf[..len].copy_from_slice(&self[offset..offset + len]); - - Ok(len) - } - - fn write(&mut self, offset: usize, buf: &[u8]) -> IoResult<usize> { - Err(IoError::PermissionDenied) - } + Ok(len) } -impl FileDevice for &'_ mut [u8] { - fn len(&self) -> usize { - self.len() - } - - fn read(&self, offset: usize, buf: &mut [u8]) -> IoResult<usize> { - self.as_ref().read(offset, buf) - } - - fn write(&mut self, offset: usize, buf: &[u8]) -> IoResult<usize> { - let len = self - .len() - .checked_sub(offset) - .ok_or(IoError::UnexpectedEOF)? - .min(buf.len()); +pub fn slice_write(this: &mut [u8], offset: usize, buf: &[u8]) -> IoResult<usize> { + let len = this + .len() + .checked_sub(offset) + .ok_or(IoError::UnexpectedEOF)? + .min(buf.len()); - self[offset..offset + len].copy_from_slice(&buf[..len]); + this[offset..offset + len].copy_from_slice(&buf[..len]); - Ok(len) - } + Ok(len) } diff --git a/src/vfs/devices.rs b/src/vfs/devices.rs index 7ea9798..5fb464e 100644 --- a/src/vfs/devices.rs +++ b/src/vfs/devices.rs @@ -3,9 +3,11 @@ use crate::{ vfs, }; +use super::Node; + // -pub fn install() { - vfs::install_dev("/dev/rtc", RtcDevice); - vfs::install_dev("/dev/hpet", HpetDevice); +pub fn install(root: Node) { + vfs::install_dev_with(root.clone(), "/dev/rtc", RtcDevice); + vfs::install_dev_with(root, "/dev/hpet", HpetDevice); } diff --git a/src/vfs/mod.rs b/src/vfs/mod.rs index 55b6a0c..1ec71e3 100644 --- a/src/vfs/mod.rs +++ b/src/vfs/mod.rs @@ -21,65 +21,35 @@ pub mod path; static _ROOT_NODE: Lazy<Root> = Lazy::new(|| Directory::from("")); pub static ROOT: Lazy<Root> = Lazy::new(|| { debug!("Initializing VFS"); - devices::install(); + devices::install(Node::Directory(_ROOT_NODE.clone())); _ROOT_NODE.clone() }); // -pub fn get_node(path: impl AsRef<Path>, make_dirs: bool) -> IoResult<Node> { - let mut node = Node::Directory(ROOT.clone()); - - for part in path.as_ref().iter() { - match node { - Node::File(_) => return Err(IoError::NotADirectory), - Node::Directory(_dir) => { - let mut dir = _dir.lock(); - // TODO: only Node::Directory should be cloned - - node = if let Ok(node) = dir.get_node(part) { - node - } else if make_dirs { - let node = Node::Directory(Directory::from(part)); - dir.create_node(part, node.clone())?; - node - } else { - return Err(IoError::NotFound); - }; - } - } - } +pub fn get_root() -> Node { + Node::Directory(ROOT.clone()) +} - Ok(node) +pub fn get_node(path: impl AsRef<Path>, make_dirs: bool) -> IoResult<Node> { + get_node_with(get_root(), path, make_dirs) } pub fn get_dir(path: impl AsRef<Path>, make_dirs: bool) -> IoResult<DirRef> { - let node = get_node(path, make_dirs)?; - match node { - Node::File(_) => Err(IoError::NotADirectory), - Node::Directory(dir) => Ok(dir), - } + get_dir_with(get_root(), path, make_dirs) } // TODO: create -pub fn get_file(path: impl AsRef<Path>, make_dirs: bool, _create: bool) -> IoResult<FileRef> { - let node = get_node(path, make_dirs)?; - match node { - Node::File(file) => Ok(file), - Node::Directory(_) => Err(IoError::IsADirectory), - } +pub fn get_file(path: impl AsRef<Path>, make_dirs: bool, create: bool) -> IoResult<FileRef> { + get_file_with(get_root(), path, make_dirs, create) } pub fn create_device(path: impl AsRef<Path>, make_dirs: bool, dev: FileRef) -> IoResult<()> { - create_node(path, make_dirs, Node::File(dev)) + create_device_with(get_root(), path, make_dirs, dev) } pub fn install_dev(path: impl AsRef<Path>, dev: impl FileDevice + Send + Sync + 'static) { - let path = path.as_ref(); - debug!("installing VFS device at {path:?}"); - if let Err(err) = create_device(path, true, Arc::new(Mutex::new(dev)) as _) { - error!("failed to install VFS device at {path:?} : {err:?}"); - } + install_dev_with(get_root(), path, dev) } pub use {get_dir as read_dir, get_file as open}; @@ -334,25 +304,20 @@ fn install_dev_with( } fn create_node_with( - node: Node, + root: Node, path: impl AsRef<Path>, make_dirs: bool, node: Node, ) -> IoResult<()> { let (parent_dir, file_name) = path.as_ref().split().ok_or(IoError::NotFound)?; - let parent_dir = get_dir(parent_dir, make_dirs)?; + let parent_dir = get_dir_with(root, parent_dir, make_dirs)?; let mut parent_dir = parent_dir.lock(); - parent_dir.create_node_with(node, file_name, node)?; + parent_dir.create_node(file_name, node)?; Ok(()) } -fn create_node(path: impl AsRef<Path>, make_dirs: bool, node: Node) -> IoResult<()> { - let (parent_dir, file_name) = path.as_ref().split().ok_or(IoError::NotFound)?; - let parent_dir = get_dir(parent_dir, make_dirs)?; - let mut parent_dir = parent_dir.lock(); - parent_dir.create_node(file_name, node)?; - - Ok(()) +fn create_node(path: impl AsRef<Path>, make_dirs: bool, node: Node) -> IoResult<()> { + create_node_with(Node::Directory(ROOT.clone()), path, make_dirs, node) } -- GitLab