From 23a17a94c12c242c15d93ac4e2f9c4f409242c67 Mon Sep 17 00:00:00 2001 From: SuchAFuriousDeath <48620541+SuchAFuriousDeath@users.noreply.github.com> Date: Sun, 18 Feb 2024 21:28:30 +0100 Subject: [PATCH 1/4] refactors idt (#661) --- src/kernel/src/budget/mod.rs | 9 +--- src/kernel/src/fs/dev/cdev.rs | 8 +++- src/kernel/src/fs/file.rs | 2 +- src/kernel/src/fs/mod.rs | 26 ++++++------ src/kernel/src/idt/entry.rs | 14 ++---- src/kernel/src/idt/mod.rs | 17 +++++++- src/kernel/src/main.rs | 3 ++ src/kernel/src/namedobj/mod.rs | 64 ++++++++++++++++++++++++++++ src/kernel/src/osem/mod.rs | 8 ++-- src/kernel/src/process/filedesc.rs | 68 +++++++++++++++++------------- src/kernel/src/process/mod.rs | 39 ----------------- src/kernel/src/regmgr/mod.rs | 7 ++- src/kernel/src/rtld/mod.rs | 5 +-- 13 files changed, 154 insertions(+), 116 deletions(-) create mode 100644 src/kernel/src/namedobj/mod.rs diff --git a/src/kernel/src/budget/mod.rs b/src/kernel/src/budget/mod.rs index 94ae333ad..4a5dc4d69 100644 --- a/src/kernel/src/budget/mod.rs +++ b/src/kernel/src/budget/mod.rs @@ -1,9 +1,8 @@ use crate::errno::{ENOENT, ENOSYS, ESRCH}; -use crate::idt::Idt; +use crate::idt::{Entry, Idt}; use crate::info; use crate::process::VThread; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; -use std::convert::Infallible; use std::sync::{Arc, Mutex}; /// An implementation of budget system on the PS4. @@ -25,12 +24,8 @@ impl BudgetManager { pub fn create(&self, budget: Budget) -> usize { let name = budget.name.clone(); let mut budgets = self.budgets.lock().unwrap(); - let (entry, id) = budgets - .alloc::<_, Infallible>(|_| Ok(Arc::new(budget))) - .unwrap(); - entry.set_name(Some(name)); - entry.set_ty(0x2000); + let id = budgets.alloc_infallible(|_| Entry::new(Some(name), Arc::new(budget), 0x2000)); id } diff --git a/src/kernel/src/fs/dev/cdev.rs b/src/kernel/src/fs/dev/cdev.rs index f9bad1f8c..aa44dc9da 100644 --- a/src/kernel/src/fs/dev/cdev.rs +++ b/src/kernel/src/fs/dev/cdev.rs @@ -207,14 +207,18 @@ pub(super) trait Device: Debug + Sync + Send + 'static { #[allow(unused_variables)] fn read( self: Arc, - data: &mut [u8], + data: &mut UioMut, td: Option<&VThread>, ) -> Result> { Err(Box::new(DefaultError::ReadNotSupported)) } #[allow(unused_variables)] - fn write(self: Arc, data: &[u8], td: Option<&VThread>) -> Result> { + fn write( + self: Arc, + data: &mut Uio, + td: Option<&VThread>, + ) -> Result> { Err(Box::new(DefaultError::WriteNotSupported)) } diff --git a/src/kernel/src/fs/file.rs b/src/kernel/src/fs/file.rs index 9779bcaeb..c367d7505 100644 --- a/src/kernel/src/fs/file.rs +++ b/src/kernel/src/fs/file.rs @@ -182,7 +182,7 @@ pub enum VFileType { bitflags! { /// Flags for [`VFile`]. - #[derive(Debug, Clone, Copy)] + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct VFileFlags: u32 { const READ = 0x00000001; // FREAD const WRITE = 0x00000002; // FWRITE diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index a64233928..8c627fe20 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -507,6 +507,19 @@ impl Fs { Ok(SysOut::ZERO) } + fn revoke(&self, vn: Arc, td: &VThread) -> Result<(), RevokeError> { + let vattr = vn.getattr().map_err(RevokeError::GetAttrError)?; + + if td.cred().effective_uid() != vattr.uid() { + td.priv_check(Privilege::VFS_ADMIN)?; + } + + vn.revoke(RevokeFlags::REVOKE_ALL) + .map_err(RevokeError::RevokeFailed)?; + + Ok(()) + } + fn sys_readv(self: &Arc, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let iovec: *mut IoVec = i.args[1].into(); @@ -728,19 +741,6 @@ impl Fs { todo!() } - fn revoke(&self, vn: Arc, td: &VThread) -> Result<(), RevokeError> { - let vattr = vn.getattr().map_err(RevokeError::GetAttrError)?; - - if td.cred().effective_uid() != vattr.uid() { - td.priv_check(Privilege::VFS_ADMIN)?; - } - - vn.revoke(RevokeFlags::REVOKE_ALL) - .map_err(RevokeError::RevokeFailed)?; - - Ok(()) - } - fn sys_mkdir(self: &Arc, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path() }?.unwrap(); let mode: u32 = i.args[1].try_into().unwrap(); diff --git a/src/kernel/src/idt/entry.rs b/src/kernel/src/idt/entry.rs index 02b6f1c44..d8b4d1c1a 100644 --- a/src/kernel/src/idt/entry.rs +++ b/src/kernel/src/idt/entry.rs @@ -7,11 +7,11 @@ pub struct Entry { } impl Entry { - pub(super) fn new(data: T) -> Self { + pub fn new(name: Option, data: T, ty: u16) -> Self { Self { - name: None, + name: name, data, - ty: 0, + ty, } } @@ -22,12 +22,4 @@ impl Entry { pub fn ty(&self) -> u16 { self.ty } - - pub fn set_name(&mut self, v: Option) { - self.name = v; - } - - pub fn set_ty(&mut self, v: u16) { - self.ty = v; - } } diff --git a/src/kernel/src/idt/mod.rs b/src/kernel/src/idt/mod.rs index cf64d0136..966f8eb39 100644 --- a/src/kernel/src/idt/mod.rs +++ b/src/kernel/src/idt/mod.rs @@ -1,3 +1,5 @@ +use std::convert::Infallible; + pub use self::entry::*; mod entry; @@ -27,10 +29,21 @@ impl Idt { } } + pub fn alloc_infallible(&mut self, factory: F) -> usize + where + F: FnOnce(usize) -> Entry, + { + let Ok((_, id)) = self.alloc::<_, Infallible>(|id| Ok(factory(id))) else { + unreachable!(); + }; + + id + } + /// See `id_alloc` on the PS4 for a reference. pub fn alloc(&mut self, factory: F) -> Result<(&mut Entry, usize), E> where - F: FnOnce(usize) -> Result, + F: FnOnce(usize) -> Result, E>, { // Allocate a new set if necessary. let id = self.next; @@ -47,7 +60,7 @@ impl Idt { assert!(entry.is_none()); // Set the value. - let value = entry.insert(Entry::new(factory(id)?)); + let value = entry.insert(factory(id)?); // Update table states. self.next += 1; diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index 15e50c8da..a5f31f238 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -8,6 +8,7 @@ use crate::kqueue::KernelQueueManager; use crate::llvm::Llvm; use crate::log::{print, LOGGER}; use crate::memory::{MemoryManager, MemoryManagerError}; +use crate::namedobj::NamedObjManager; use crate::net::NetManager; use crate::osem::OsemManager; use crate::process::{VProc, VProcInitError, VThread}; @@ -47,6 +48,7 @@ mod kqueue; mod llvm; mod log; mod memory; +mod namedobj; mod net; mod osem; mod process; @@ -289,6 +291,7 @@ fn run( &mut syscalls, )?; + NamedObjManager::new(&mut syscalls, &proc); OsemManager::new(&mut syscalls, &proc); // Initialize runtime linker. diff --git a/src/kernel/src/namedobj/mod.rs b/src/kernel/src/namedobj/mod.rs new file mode 100644 index 000000000..bb8085956 --- /dev/null +++ b/src/kernel/src/namedobj/mod.rs @@ -0,0 +1,64 @@ +use crate::{ + errno::EINVAL, + idt::Entry, + info, + process::VProc, + syscalls::{SysErr, SysIn, SysOut, Syscalls}, +}; +use std::sync::Arc; + +pub struct NamedObjManager { + proc: Arc, +} + +impl NamedObjManager { + pub fn new(sys: &mut Syscalls, proc: &Arc) -> Arc { + let namedobj = Arc::new(Self { proc: proc.clone() }); + + sys.register(557, &namedobj, Self::sys_namedobj_create); + + namedobj + } + + fn sys_namedobj_create(self: &Arc, i: &SysIn) -> Result { + // Get arguments. + let name = unsafe { i.args[0].to_str(32) }?.ok_or(SysErr::Raw(EINVAL))?; + let data: usize = i.args[1].into(); + let flags: u32 = i.args[2].try_into().unwrap(); + + // Allocate the entry. + let mut table = self.proc.objects_mut(); + + let obj = NamedObj::new(name, data); + + let id = table.alloc_infallible(|_| { + Entry::new( + Some(name.to_owned()), + Arc::new(obj), + (flags as u16) | 0x1000, + ) + }); + + info!( + "Named object '{}' (ID = {}) was created with data = {:#x} and flags = {:#x}.", + name, id, data, flags + ); + + Ok(id.into()) + } +} + +#[derive(Debug)] +pub struct NamedObj { + name: String, + data: usize, +} + +impl NamedObj { + pub fn new(name: impl Into, data: usize) -> Self { + Self { + name: name.into(), + data, + } + } +} diff --git a/src/kernel/src/osem/mod.rs b/src/kernel/src/osem/mod.rs index 25acd1310..80988a15e 100644 --- a/src/kernel/src/osem/mod.rs +++ b/src/kernel/src/osem/mod.rs @@ -1,8 +1,8 @@ use crate::errno::EINVAL; +use crate::idt::Entry; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use crate::VProc; use bitflags::bitflags; -use std::convert::Infallible; use std::sync::Arc; pub struct OsemManager { @@ -37,10 +37,8 @@ impl OsemManager { let mut objects = self.proc.objects_mut(); - let (entry, id) = objects.alloc::<_, Infallible>(|_| Ok(Osem::new(flags)))?; - - entry.set_name(Some(name.to_owned())); - entry.set_ty(0x120); + let id = objects + .alloc_infallible(|_| Entry::new(Some(name.to_owned()), Osem::new(flags), 0x120)); Ok(id.into()) } diff --git a/src/kernel/src/process/filedesc.rs b/src/kernel/src/process/filedesc.rs index e546c84b5..2a3dba04d 100644 --- a/src/kernel/src/process/filedesc.rs +++ b/src/kernel/src/process/filedesc.rs @@ -6,7 +6,7 @@ use gmtx::{Gutex, GutexGroup}; use macros::Errno; use std::collections::VecDeque; use std::convert::Infallible; -use std::num::NonZeroI32; +use std::num::{NonZeroI32, TryFromIntError}; use std::sync::Arc; use thiserror::Error; @@ -90,11 +90,11 @@ impl FileDesc { return i as i32; } - // This should never happened. + // This should never happen. panic!("Too many files has been opened."); } - // TODO: implement capabilities + // TODO: (maybe) implement capabilities /// See `fget` on the PS4 for a reference. pub fn get(&self, fd: i32) -> Result, GetFileError> { @@ -113,27 +113,28 @@ impl FileDesc { /// See `_fget` and `fget_unlocked` on the PS4 for a reference. fn get_internal(&self, fd: i32, flags: VFileFlags) -> Result, GetFileError> { - if fd < 0 { - return Err(GetFileError::NegativeFd(fd)); - } + let fd: usize = fd.try_into()?; let files = self.files.write(); - if fd as usize >= files.len() { - return Err(GetFileError::FdOutOfRange(fd)); - } + let file = files + .get(fd as usize) + .ok_or(GetFileError::FdOutOfRange)? // None means the file descriptor is out of range + .as_ref() + .ok_or(GetFileError::NoFile)?; // Some(None) means the file descriptor is not associated with a file - loop { - if let None = files.get(fd as usize) { - return Err(GetFileError::NoFile(fd)); + match flags { + VFileFlags::WRITE | VFileFlags::READ if !file.flags().intersects(flags) => { + return Err(GetFileError::BadFlags(flags, file.flags())); } - - todo!() + _ => {} } + + Ok(file.clone()) } pub fn free(&self, fd: i32) -> Result<(), FreeError> { - let fd: usize = fd.try_into().map_err(|_| FreeError::NegativeFd)?; + let fd: usize = fd.try_into()?; let mut files = self.files.write(); @@ -147,25 +148,28 @@ impl FileDesc { } } -#[derive(Debug, Error)] +#[derive(Debug, Error, Errno)] pub enum GetFileError { - #[error("got negative file descriptor {0}")] - NegativeFd(i32), + #[error("got negative file descriptor")] + #[errno(EBADF)] + NegativeFd, - #[error("file descriptor {0} out of range")] - FdOutOfRange(i32), + #[error("file descriptor is out of range")] + #[errno(EBADF)] + FdOutOfRange, - #[error("no file assoiated with file descriptor {0}")] - NoFile(i32), + #[error("no file assoiated with file descriptor")] + #[errno(EBADF)] + NoFile, + + #[error("bad flags associated with file descriptor: expected {0:?}, file has {1:?}")] + #[errno(EBADF)] + BadFlags(VFileFlags, VFileFlags), } -impl Errno for GetFileError { - fn errno(&self) -> NonZeroI32 { - match self { - Self::NegativeFd(_) => EBADF, - Self::FdOutOfRange(_) => EBADF, - Self::NoFile(_) => EBADF, - } +impl From for GetFileError { + fn from(_: TryFromIntError) -> Self { + GetFileError::NegativeFd } } @@ -193,3 +197,9 @@ pub enum FreeError { #[errno(EBADF)] NoFile, } + +impl From for FreeError { + fn from(_: TryFromIntError) -> Self { + FreeError::NegativeFd + } +} diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index 25c005679..f95380830 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -22,7 +22,6 @@ use crate::ucred::{AuthInfo, Gid, Privilege, Ucred, Uid}; use gmtx::{Gutex, GutexGroup, GutexWriteGuard}; use std::any::Any; use std::cmp::min; -use std::convert::Infallible; use std::ffi::c_char; use std::mem::zeroed; use std::num::NonZeroI32; @@ -117,7 +116,6 @@ impl VProc { sys.register(464, &vp, Self::sys_thr_set_name); sys.register(466, &vp, Self::sys_rtprio_thread); sys.register(487, &vp, Self::sys_cpuset_getaffinity); - sys.register(557, &vp, Self::sys_namedobj_create); sys.register(585, &vp, Self::sys_is_in_sandbox); sys.register(587, &vp, Self::sys_get_authinfo); sys.register(602, &vp, Self::sys_randomized_path); @@ -550,30 +548,6 @@ impl VProc { } } - // TODO: This should not be here. - fn sys_namedobj_create(self: &Arc, i: &SysIn) -> Result { - // Get arguments. - let name = unsafe { i.args[0].to_str(32)?.ok_or(SysErr::Raw(EINVAL))? }; - let data: usize = i.args[1].into(); - let flags: u32 = i.args[2].try_into().unwrap(); - - // Allocate the entry. - let mut table = self.objects.write(); - let (entry, id) = table - .alloc::<_, Infallible>(|_| Ok(Arc::new(NamedObj::new(name.to_owned(), data)))) - .unwrap(); - - entry.set_name(Some(name.to_owned())); - entry.set_ty((flags as u16) | 0x1000); - - info!( - "Named object '{}' (ID = {}) was created with data = {:#x} and flags = {:#x}.", - name, id, data, flags - ); - - Ok(id.into()) - } - fn sys_is_in_sandbox(self: &Arc, _: &SysIn) -> Result { // TODO: Implement this once FS rework has been usable. Ok(1.into()) @@ -664,19 +638,6 @@ struct RtPrio { prio: u16, } -/// TODO: Move this to somewhere else. -#[derive(Debug)] -pub struct NamedObj { - name: String, - data: usize, -} - -impl NamedObj { - pub fn new(name: String, data: usize) -> Self { - Self { name, data } - } -} - /// Represents an error when [`VProc`] construction is failed. #[derive(Debug, Error)] pub enum VProcInitError { diff --git a/src/kernel/src/regmgr/mod.rs b/src/kernel/src/regmgr/mod.rs index 563b356d4..de79fa0ef 100644 --- a/src/kernel/src/regmgr/mod.rs +++ b/src/kernel/src/regmgr/mod.rs @@ -350,10 +350,9 @@ impl RegMgr { let mut out = 0; let ret = self.get_int(key, &mut out).unwrap(); - if ret == 0 { - Ok(out.into()) - } else { - Err(SysErr::Raw(unsafe { NonZeroI32::new_unchecked(ret) })) + match NonZeroI32::new(ret) { + None => Ok(ret.into()), + Some(v) => Err(SysErr::Raw(v)), } } _ => Err(SysErr::Raw(EINVAL)), diff --git a/src/kernel/src/rtld/mod.rs b/src/kernel/src/rtld/mod.rs index 9ed800cc5..d51efd321 100644 --- a/src/kernel/src/rtld/mod.rs +++ b/src/kernel/src/rtld/mod.rs @@ -5,6 +5,7 @@ use crate::budget::ProcType; use crate::ee::{ExecutionEngine, RawFn}; use crate::errno::{Errno, EINVAL, ENOENT, ENOEXEC, ENOMEM, EPERM, ESRCH}; use crate::fs::{Fs, OpenError, VPath, VPathBuf}; +use crate::idt::Entry; use crate::info; use crate::log::print; use crate::memory::{MemoryManager, MemoryUpdateError, MmapError, Protections}; @@ -271,11 +272,9 @@ impl RuntimeLinker { return Err(LoadError::SetupFailed(e)); } - Ok(Arc::new(md)) + Ok(Entry::new(None, Arc::new(md), 0x2000)) })?; - entry.set_ty(0x2000); - // Add to list. let module = entry.data().clone().downcast::>().unwrap(); From 788bbb9836c2e697399407eeff7202771580a123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Wed, 21 Feb 2024 15:14:58 +0000 Subject: [PATCH 2/4] Implement name2oid vm.budgets.mlock_total and kern.pseudo_rng (#673) --- src/kernel/src/sysctl/mod.rs | 57 ++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/kernel/src/sysctl/mod.rs b/src/kernel/src/sysctl/mod.rs index 8211367fa..469af996a 100644 --- a/src/kernel/src/sysctl/mod.rs +++ b/src/kernel/src/sysctl/mod.rs @@ -83,6 +83,7 @@ impl Sysctl { pub const KERN_ARND: i32 = 37; pub const KERN_SDKVERSION: i32 = 38; pub const KERN_CPUMODE: i32 = 41; + pub const KERN_RNGPSEUDO: i32 = 47; pub const KERN_PROC_APPINFO: i32 = 35; pub const KERN_PROC_SANITIZER: i32 = 41; pub const KERN_PROC_PTC: i32 = 43; @@ -94,6 +95,7 @@ impl Sysctl { pub const VM_BUDGETS: i32 = 313; pub const VM_BUDGETS_MLOCK_AVAIL: i32 = 314; + pub const VM_BUDGETS_MLOCK_TOTAL: i32 = 315; pub const HW_PAGESIZE: i32 = 7; @@ -442,6 +444,16 @@ impl Sysctl { todo!() } + fn kern_rngpseudo( + &self, + _: &'static Oid, + _: &Arg, + _: usize, + _req: &mut SysctlReq, + ) -> Result<(), SysErr> { + todo!() + } + fn budgets_mlock_avail( &self, _: &'static Oid, @@ -452,6 +464,16 @@ impl Sysctl { todo!() } + fn budgets_mlock_total( + &self, + _: &'static Oid, + _: &Arg, + _: usize, + _req: &mut SysctlReq, + ) -> Result<(), SysErr> { + todo!() + } + fn machdep_tsc_freq( &self, oid: &'static Oid, @@ -633,6 +655,8 @@ type Handler = fn(&Sysctl, &'static Oid, &Arg, usize, &mut SysctlReq) -> Result< // └─── (1.42) KERN_SCHED // └─── ... // └─── (1.42.1252) KERN_SCHED_CPUSETSIZE +// └─── (1.47) KERN_RNGPSEUDO +// └─── ... // └─── (1.1157) // └─── ... // └─── (1.1157.1162) KERN_SMP_CPUS @@ -645,6 +669,7 @@ type Handler = fn(&Sysctl, &'static Oid, &Arg, usize, &mut SysctlReq) -> Result< // └─── (2.1.572) VM_PS4DEV_TRCMEM_AVAIL // └─── (2.313) VM_BUDGETS // └─── (2.313.314) VM_BUDGETS_MLOCK_AVAIL +// └─── (2.313.315) VM_BUDGETS_MLOCK_TOTAL // └─── ... // └─── (3) VFS // └─── ... @@ -835,7 +860,7 @@ static KERN_SDKVERSION: Oid = Oid { static KERN_CPUMODE: Oid = Oid { parent: &KERN_CHILDREN, - link: Some(&KERN_SCHED), // TODO: Use a proper value. + link: Some(&KERN_RNGPSEUDO), // TODO: Use a proper value. number: Sysctl::KERN_CPUMODE, kind: Sysctl::CTLFLAG_RD | Sysctl::CTLFLAG_MPSAFE | Sysctl::CTLTYPE_INT, arg1: None, @@ -847,6 +872,20 @@ static KERN_CPUMODE: Oid = Oid { enabled: true, }; +static KERN_RNGPSEUDO: Oid = Oid { + parent: &KERN_CHILDREN, + link: Some(&KERN_SCHED), // TODO: Use a proper value. + number: Sysctl::KERN_RNGPSEUDO, + kind: Sysctl::CTLFLAG_RD | Sysctl::CTLFLAG_MPSAFE | Sysctl::CTLTYPE_OPAQUE, + arg1: None, + arg2: 0, + name: "rng_pseudo", + handler: Some(Sysctl::kern_rngpseudo), + fmt: "", + descr: "RNGPseudo", + enabled: true, +}; + static KERN_SCHED: Oid = Oid { parent: &KERN_CHILDREN, link: Some(&KERN_SMP), // TODO: Use a proper value. @@ -995,7 +1034,7 @@ static VM_BUDGETS_CHILDREN: OidList = OidList { static VM_BUDGETS_MLOCK_AVAIL: Oid = Oid { parent: &VM_BUDGETS_CHILDREN, - link: None, + link: Some(&VM_BUDGETS_MLOCK_TOTAL), number: Sysctl::VM_BUDGETS_MLOCK_AVAIL, kind: Sysctl::CTLFLAG_RD | Sysctl::CTLTYPE_ULONG, arg1: None, @@ -1007,6 +1046,20 @@ static VM_BUDGETS_MLOCK_AVAIL: Oid = Oid { enabled: true, }; +static VM_BUDGETS_MLOCK_TOTAL: Oid = Oid { + parent: &VM_BUDGETS_CHILDREN, + link: None, + number: Sysctl::VM_BUDGETS_MLOCK_TOTAL, + kind: Sysctl::CTLFLAG_RD | Sysctl::CTLTYPE_ULONG, + arg1: None, + arg2: 0, + name: "mlock_total", + handler: Some(Sysctl::budgets_mlock_total), + fmt: "L", + descr: "Total MLOCK budget", + enabled: true, +}; + static HW: Oid = Oid { parent: &CHILDREN, link: Some(&MACHDEP), From 6f740f38afacc199657a004cfbfedcd16f88184e Mon Sep 17 00:00:00 2001 From: SuchAFuriousDeath <48620541+SuchAFuriousDeath@users.noreply.github.com> Date: Wed, 21 Feb 2024 21:32:08 +0100 Subject: [PATCH 3/4] makes syscall handlers take a &VThread (#676) --- src/kernel/src/arch/mod.rs | 3 +- src/kernel/src/budget/mod.rs | 3 +- src/kernel/src/dmem/mod.rs | 5 +- src/kernel/src/fs/mod.rs | 99 ++++++++++++---------------------- src/kernel/src/kqueue/mod.rs | 6 +-- src/kernel/src/memory/mod.rs | 8 +-- src/kernel/src/namedobj/mod.rs | 4 +- src/kernel/src/net/mod.rs | 12 ++--- src/kernel/src/osem/mod.rs | 3 +- src/kernel/src/process/mod.rs | 41 +++++++------- src/kernel/src/regmgr/mod.rs | 5 +- src/kernel/src/rtld/mod.rs | 28 +++++++--- src/kernel/src/shm/mod.rs | 6 +-- src/kernel/src/syscalls/mod.rs | 49 ++++++++--------- src/kernel/src/sysctl/mod.rs | 9 +--- src/kernel/src/time/mod.rs | 5 +- 16 files changed, 126 insertions(+), 160 deletions(-) diff --git a/src/kernel/src/arch/mod.rs b/src/kernel/src/arch/mod.rs index b7f4384c8..60486c3ba 100644 --- a/src/kernel/src/arch/mod.rs +++ b/src/kernel/src/arch/mod.rs @@ -31,10 +31,9 @@ impl MachDep { mach } - fn sysarch(self: &Arc, i: &SysIn) -> Result { + fn sysarch(self: &Arc, td: &VThread, i: &SysIn) -> Result { let op: u32 = i.args[0].try_into().unwrap(); let parms: *mut u8 = i.args[1].into(); - let td = VThread::current().unwrap(); let mut pcb = td.pcb_mut(); if op < 2 { diff --git a/src/kernel/src/budget/mod.rs b/src/kernel/src/budget/mod.rs index 4a5dc4d69..04f949eea 100644 --- a/src/kernel/src/budget/mod.rs +++ b/src/kernel/src/budget/mod.rs @@ -30,10 +30,9 @@ impl BudgetManager { id } - fn sys_budget_get_ptype(self: &Arc, i: &SysIn) -> Result { + fn sys_budget_get_ptype(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Check if PID is our process. let pid: i32 = i.args[0].try_into().unwrap(); - let td = VThread::current().unwrap(); info!("Getting budget process type for process {pid}."); diff --git a/src/kernel/src/dmem/mod.rs b/src/kernel/src/dmem/mod.rs index 3f7bd5aa1..65551bdd8 100644 --- a/src/kernel/src/dmem/mod.rs +++ b/src/kernel/src/dmem/mod.rs @@ -23,8 +23,7 @@ impl DmemManager { dmem } - fn sys_dmem_container(self: &Arc, i: &SysIn) -> Result { - let td = VThread::current().unwrap(); + fn sys_dmem_container(self: &Arc, td: &VThread, i: &SysIn) -> Result { let set: i32 = i.args[0].try_into().unwrap(); let get: i32 = td.proc().dmem_container().try_into().unwrap(); @@ -35,7 +34,7 @@ impl DmemManager { Ok(get.into()) } - fn sys_blockpool_open(self: &Arc, i: &SysIn) -> Result { + fn sys_blockpool_open(self: &Arc, td: &VThread, i: &SysIn) -> Result { let flags: u32 = i.args[0].try_into().unwrap(); if flags & 0xffafffff != 0 { diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index 8c627fe20..2cb933330 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -265,7 +265,7 @@ impl Fs { Ok(vn) } - fn sys_read(self: &Arc, i: &SysIn) -> Result { + fn sys_read(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let ptr: *mut u8 = i.args[1].into(); let len: usize = i.args[2].try_into().unwrap(); @@ -277,7 +277,7 @@ impl Fs { bytes_left: len, }; - self.readv(fd, uio) + self.readv(fd, uio, td) } /// See `vfs_donmount` on the PS4 for a reference. @@ -375,7 +375,7 @@ impl Fs { } } - fn sys_write(self: &Arc, i: &SysIn) -> Result { + fn sys_write(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let ptr: *const u8 = i.args[1].into(); let len: usize = i.args[2].into(); @@ -387,10 +387,10 @@ impl Fs { bytes_left: len, }; - self.writev(fd, uio) + self.writev(fd, uio, td) } - fn sys_open(self: &Arc, i: &SysIn) -> Result { + fn sys_open(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let path = unsafe { i.args[0].to_path()?.unwrap() }; let flags: OpenFlags = i.args[1].try_into().unwrap(); @@ -421,7 +421,6 @@ impl Fs { info!("Opening {path} with flags = {flags}."); // Lookup file. - let td = VThread::current().unwrap(); let mut file = self.open(path, Some(&td))?; *file.flags_mut() = flags.into_fflags(); @@ -434,8 +433,7 @@ impl Fs { Ok(fd.into()) } - fn sys_close(self: &Arc, i: &SysIn) -> Result { - let td = VThread::current().unwrap(); + fn sys_close(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); info!("Closing fd {fd}."); @@ -445,13 +443,11 @@ impl Fs { Ok(SysOut::ZERO) } - fn sys_ioctl(self: &Arc, i: &SysIn) -> Result { + fn sys_ioctl(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); // Our IoCmd contains both the command and the argument (if there is one). let cmd = IoCmd::try_from_raw_parts(i.args[1].into(), i.args[2].into())?; - let td = VThread::current().unwrap(); - info!("Executing ioctl({cmd:?}) on file descriptor {fd}."); self.ioctl(fd, cmd, &td)?; @@ -483,13 +479,12 @@ impl Fs { Ok(SysOut::ZERO) } - fn sys_revoke(self: &Arc, i: &SysIn) -> Result { + fn sys_revoke(self: &Arc, td: &VThread, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path()?.unwrap() }; info!("Revoking access to {path}."); // Check current thread privilege. - let td = VThread::current().unwrap(); td.priv_check(Privilege::SCE683)?; @@ -520,19 +515,17 @@ impl Fs { Ok(()) } - fn sys_readv(self: &Arc, i: &SysIn) -> Result { + fn sys_readv(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let iovec: *mut IoVec = i.args[1].into(); let count: u32 = i.args[2].try_into().unwrap(); let uio = unsafe { UioMut::copyin(iovec, count) }?; - self.readv(fd, uio) + self.readv(fd, uio, td) } - fn readv(&self, fd: i32, uio: UioMut) -> Result { - let td = VThread::current().unwrap(); - + fn readv(&self, fd: i32, uio: UioMut, td: &VThread) -> Result { let file = td.proc().files().get_for_read(fd)?; let read = file.do_read(uio, Offset::Current, Some(&td))?; @@ -540,19 +533,17 @@ impl Fs { Ok(read.into()) } - fn sys_writev(self: &Arc, i: &SysIn) -> Result { + fn sys_writev(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let iovec: *const IoVec = i.args[1].into(); let iovcnt: u32 = i.args[2].try_into().unwrap(); let uio = unsafe { Uio::copyin(iovec, iovcnt) }?; - self.writev(fd, uio) + self.writev(fd, uio, td) } - fn writev(&self, fd: i32, uio: Uio) -> Result { - let td = VThread::current().unwrap(); - + fn writev(&self, fd: i32, uio: Uio, td: &VThread) -> Result { let file = td.proc().files().get_for_write(fd)?; let written = file.do_write(uio, Offset::Current, Some(&td))?; @@ -560,12 +551,10 @@ impl Fs { Ok(written.into()) } - fn sys_stat(self: &Arc, i: &SysIn) -> Result { + fn sys_stat(self: &Arc, td: &VThread, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path() }?.unwrap(); let stat_out: *mut Stat = i.args[1].into(); - let td = VThread::current().unwrap(); - let stat = self.stat(path, &td)?; unsafe { @@ -580,12 +569,10 @@ impl Fs { self.statat(AtFlags::empty(), At::Cwd, path, td) } - fn sys_fstat(self: &Arc, i: &SysIn) -> Result { + fn sys_fstat(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let stat_out: *mut Stat = i.args[1].into(); - let td = VThread::current().unwrap(); - let stat = self.fstat(fd, &td)?; unsafe { @@ -601,12 +588,10 @@ impl Fs { todo!() } - fn sys_lstat(self: &Arc, i: &SysIn) -> Result { + fn sys_lstat(self: &Arc, td: &VThread, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path() }?.unwrap(); let stat_out: *mut Stat = i.args[1].into(); - let td = VThread::current().unwrap(); - td.priv_check(Privilege::SCE683)?; let stat = self.lstat(path, &td)?; @@ -623,7 +608,7 @@ impl Fs { self.statat(AtFlags::SYMLINK_NOFOLLOW, At::Cwd, path, td) } - fn sys_pread(self: &Arc, i: &SysIn) -> Result { + fn sys_pread(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let ptr: *mut u8 = i.args[1].into(); let len: usize = i.args[2].try_into().unwrap(); @@ -636,10 +621,10 @@ impl Fs { bytes_left: len, }; - self.preadv(fd, uio, offset) + self.preadv(fd, uio, offset, td) } - fn sys_pwrite(self: &Arc, i: &SysIn) -> Result { + fn sys_pwrite(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let ptr: *mut u8 = i.args[1].into(); let len: usize = i.args[2].try_into().unwrap(); @@ -652,10 +637,10 @@ impl Fs { bytes_left: len, }; - self.pwritev(fd, uio, offset) + self.pwritev(fd, uio, offset, td) } - fn sys_preadv(self: &Arc, i: &SysIn) -> Result { + fn sys_preadv(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let iovec: *mut IoVec = i.args[1].into(); let count: u32 = i.args[2].try_into().unwrap(); @@ -663,12 +648,10 @@ impl Fs { let uio = unsafe { UioMut::copyin(iovec, count) }?; - self.preadv(fd, uio, offset) + self.preadv(fd, uio, offset, td) } - fn preadv(&self, fd: i32, uio: UioMut, off: u64) -> Result { - let td = VThread::current().unwrap(); - + fn preadv(&self, fd: i32, uio: UioMut, off: u64, td: &VThread) -> Result { let file = td.proc().files().get_for_read(fd)?; if !file.is_seekable() { @@ -682,7 +665,7 @@ impl Fs { Ok(read.into()) } - fn sys_pwritev(self: &Arc, i: &SysIn) -> Result { + fn sys_pwritev(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let iovec: *const IoVec = i.args[1].into(); let count: u32 = i.args[2].try_into().unwrap(); @@ -690,12 +673,10 @@ impl Fs { let uio = unsafe { Uio::copyin(iovec, count) }?; - self.pwritev(fd, uio, offset) + self.pwritev(fd, uio, offset, td) } - fn pwritev(&self, fd: i32, uio: Uio, off: u64) -> Result { - let td = VThread::current().unwrap(); - + fn pwritev(&self, fd: i32, uio: Uio, off: u64, td: &VThread) -> Result { let file = td.proc().files().get_for_write(fd)?; if !file.is_seekable() { @@ -709,14 +690,12 @@ impl Fs { Ok(written.into()) } - fn sys_fstatat(self: &Arc, i: &SysIn) -> Result { + fn sys_fstatat(self: &Arc, td: &VThread, i: &SysIn) -> Result { let dirfd: i32 = i.args[0].try_into().unwrap(); let path = unsafe { i.args[1].to_path() }?.unwrap(); let stat_out: *mut Stat = i.args[2].into(); let flags: AtFlags = i.args[3].try_into().unwrap(); - let td = VThread::current().unwrap(); - td.priv_check(Privilege::SCE683)?; let stat = self.statat(flags, At::Fd(dirfd), path, &td)?; @@ -741,17 +720,15 @@ impl Fs { todo!() } - fn sys_mkdir(self: &Arc, i: &SysIn) -> Result { + fn sys_mkdir(self: &Arc, td: &VThread, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path() }?.unwrap(); let mode: u32 = i.args[1].try_into().unwrap(); - let td = VThread::current().unwrap(); - self.mkdirat(At::Cwd, path, mode, Some(&td)) } #[allow(unused_variables)] - fn sys_poll(self: &Arc, i: &SysIn) -> Result { + fn sys_poll(self: &Arc, _td: &VThread, i: &SysIn) -> Result { let fds: *mut PollFd = i.args[0].into(); let nfds: u32 = i.args[1].try_into().unwrap(); let timeout: i32 = i.args[2].try_into().unwrap(); @@ -759,7 +736,7 @@ impl Fs { todo!() } - fn sys_lseek(self: &Arc, i: &SysIn) -> Result { + fn sys_lseek(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let mut offset: i64 = i.args[1].into(); let whence: Whence = { @@ -768,8 +745,6 @@ impl Fs { whence.try_into()? }; - let td = VThread::current().unwrap(); - let file = td.proc().files().get(fd)?; if !file.is_seekable() { @@ -799,12 +774,10 @@ impl Fs { todo!() } - fn sys_truncate(self: &Arc, i: &SysIn) -> Result { + fn sys_truncate(self: &Arc, td: &VThread, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_path() }?.unwrap(); let length = i.args[1].into(); - let td = VThread::current().unwrap(); - self.truncate(path, length, &td)?; Ok(SysOut::ZERO) @@ -818,12 +791,10 @@ impl Fs { todo!() } - fn sys_ftruncate(self: &Arc, i: &SysIn) -> Result { + fn sys_ftruncate(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd = i.args[0].try_into().unwrap(); let length = i.args[1].into(); - let td = VThread::current().unwrap(); - self.ftruncate(fd, length, &td)?; Ok(SysOut::ZERO) @@ -843,9 +814,7 @@ impl Fs { Ok(()) } - fn sys_mkdirat(self: &Arc, i: &SysIn) -> Result { - let td = VThread::current().unwrap(); - + fn sys_mkdirat(self: &Arc, td: &VThread, i: &SysIn) -> Result { td.priv_check(Privilege::SCE683)?; let fd: i32 = i.args[0].try_into().unwrap(); diff --git a/src/kernel/src/kqueue/mod.rs b/src/kernel/src/kqueue/mod.rs index d6c83c1ab..36bf0768c 100644 --- a/src/kernel/src/kqueue/mod.rs +++ b/src/kernel/src/kqueue/mod.rs @@ -19,13 +19,11 @@ impl KernelQueueManager { kq } - fn sys_kqueueex(self: &Arc, _: &SysIn) -> Result { + fn sys_kqueueex(self: &Arc, _: &VThread, _: &SysIn) -> Result { todo!() } - fn sys_kqueue(self: &Arc, _: &SysIn) -> Result { - let td = VThread::current().unwrap(); - + fn sys_kqueue(self: &Arc, td: &VThread, _: &SysIn) -> Result { let filedesc = td.proc().files(); let fd = filedesc.alloc_with_budget::( diff --git a/src/kernel/src/memory/mod.rs b/src/kernel/src/memory/mod.rs index 2d9e197ee..8461c5bbd 100644 --- a/src/kernel/src/memory/mod.rs +++ b/src/kernel/src/memory/mod.rs @@ -534,17 +534,17 @@ impl MemoryManager { }) } - fn sys_sbrk(self: &Arc, _: &SysIn) -> Result { + fn sys_sbrk(self: &Arc, _: &VThread, _: &SysIn) -> Result { // Return EOPNOTSUPP (Not yet implemented syscall) Err(SysErr::Raw(EOPNOTSUPP)) } - fn sys_sstk(self: &Arc, _: &SysIn) -> Result { + fn sys_sstk(self: &Arc, _: &VThread, _: &SysIn) -> Result { // Return EOPNOTSUPP (Not yet implemented syscall) Err(SysErr::Raw(EOPNOTSUPP)) } - fn sys_mmap(self: &Arc, i: &SysIn) -> Result { + fn sys_mmap(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let addr: usize = i.args[0].into(); let len: usize = i.args[1].into(); @@ -594,7 +594,7 @@ impl MemoryManager { Ok(pages.into_raw().into()) } - fn sys_mname(self: &Arc, i: &SysIn) -> Result { + fn sys_mname(self: &Arc, td: &VThread, i: &SysIn) -> Result { let addr: usize = i.args[0].into(); let len: usize = i.args[1].into(); let name = unsafe { i.args[2].to_str(32)?.unwrap() }; diff --git a/src/kernel/src/namedobj/mod.rs b/src/kernel/src/namedobj/mod.rs index bb8085956..231887cec 100644 --- a/src/kernel/src/namedobj/mod.rs +++ b/src/kernel/src/namedobj/mod.rs @@ -2,7 +2,7 @@ use crate::{ errno::EINVAL, idt::Entry, info, - process::VProc, + process::{VProc, VThread}, syscalls::{SysErr, SysIn, SysOut, Syscalls}, }; use std::sync::Arc; @@ -20,7 +20,7 @@ impl NamedObjManager { namedobj } - fn sys_namedobj_create(self: &Arc, i: &SysIn) -> Result { + fn sys_namedobj_create(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let name = unsafe { i.args[0].to_str(32) }?.ok_or(SysErr::Raw(EINVAL))?; let data: usize = i.args[1].into(); diff --git a/src/kernel/src/net/mod.rs b/src/kernel/src/net/mod.rs index fb816fd8f..19ee5f24c 100644 --- a/src/kernel/src/net/mod.rs +++ b/src/kernel/src/net/mod.rs @@ -26,13 +26,11 @@ impl NetManager { net } - fn sys_socket(self: &Arc, i: &SysIn) -> Result { + fn sys_socket(self: &Arc, td: &VThread, i: &SysIn) -> Result { let domain: i32 = i.args[0].try_into().unwrap(); let ty: i32 = i.args[1].try_into().unwrap(); let proto: i32 = i.args[2].try_into().unwrap(); - let td = VThread::current().unwrap(); - let budget = if domain == 1 { BudgetType::FdIpcSocket } else { @@ -41,7 +39,7 @@ impl NetManager { let fd = td.proc().files().alloc_with_budget::( |_| { - let so = Socket::new(domain, ty, proto, td.as_ref().cred(), td.as_ref(), None)?; + let so = Socket::new(domain, ty, proto, td.cred(), td, None)?; let ty = if domain == 1 { VFileType::IpcSocket(so) @@ -58,14 +56,12 @@ impl NetManager { Ok(fd.into()) } - fn sys_socketex(self: &Arc, i: &SysIn) -> Result { + fn sys_socketex(self: &Arc, td: &VThread, i: &SysIn) -> Result { let name = unsafe { i.args[0].to_str(32)? }; let domain: i32 = i.args[1].try_into().unwrap(); let ty: i32 = i.args[2].try_into().unwrap(); let proto: i32 = i.args[3].try_into().unwrap(); - let td = VThread::current().unwrap(); - let budget = if domain == 1 { BudgetType::FdIpcSocket } else { @@ -74,7 +70,7 @@ impl NetManager { let fd = td.proc().files().alloc_with_budget::( |_| { - let so = Socket::new(domain, ty, proto, td.as_ref().cred(), td.as_ref(), name)?; + let so = Socket::new(domain, ty, proto, td.cred(), td, name)?; let ty = if domain == 1 { VFileType::IpcSocket(so) diff --git a/src/kernel/src/osem/mod.rs b/src/kernel/src/osem/mod.rs index 80988a15e..b25d3a7e7 100644 --- a/src/kernel/src/osem/mod.rs +++ b/src/kernel/src/osem/mod.rs @@ -1,5 +1,6 @@ use crate::errno::EINVAL; use crate::idt::Entry; +use crate::process::VThread; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use crate::VProc; use bitflags::bitflags; @@ -18,7 +19,7 @@ impl OsemManager { osem } - fn sys_osem_create(self: &Arc, i: &SysIn) -> Result { + fn sys_osem_create(self: &Arc, td: &VThread, i: &SysIn) -> Result { let name = unsafe { i.args[0].to_str(32) }?.unwrap(); let flags = { let flags = i.args[1].try_into().unwrap(); diff --git a/src/kernel/src/process/mod.rs b/src/kernel/src/process/mod.rs index f95380830..b5abe3da1 100644 --- a/src/kernel/src/process/mod.rs +++ b/src/kernel/src/process/mod.rs @@ -107,7 +107,7 @@ impl VProc { gg, }); - sys.register(20, &vp, |p, _| Ok(p.id().into())); + sys.register(20, &vp, Self::sys_getpid); sys.register(50, &vp, Self::sys_setlogin); sys.register(147, &vp, Self::sys_setsid); sys.register(340, &vp, Self::sys_sigprocmask); @@ -175,11 +175,13 @@ impl VProc { &self.gg } - fn sys_setlogin(self: &Arc, i: &SysIn) -> Result { + fn sys_getpid(self: &Arc, _: &VThread, _: &SysIn) -> Result { + Ok(self.id.into()) + } + + fn sys_setlogin(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Check current thread privilege. - VThread::current() - .unwrap() - .priv_check(Privilege::PROC_SETLOGIN)?; + td.priv_check(Privilege::PROC_SETLOGIN)?; // Get login name. let login = unsafe { i.args[0].to_str(17) } @@ -203,9 +205,9 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_setsid(self: &Arc, _: &SysIn) -> Result { + fn sys_setsid(self: &Arc, td: &VThread, _: &SysIn) -> Result { // Check if current thread has privilege. - VThread::current().unwrap().priv_check(Privilege::SCE680)?; + td.priv_check(Privilege::SCE680)?; // Check if the process already become a group leader. let mut group = self.group.write(); @@ -223,7 +225,7 @@ impl VProc { Ok(self.id.into()) } - fn sys_sigprocmask(self: &Arc, i: &SysIn) -> Result { + fn sys_sigprocmask(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let how: i32 = i.args[0].try_into().unwrap(); let set: *const SignalSet = i.args[1].into(); @@ -238,8 +240,7 @@ impl VProc { // Keep the current mask for copying to the oset. We need to copy to the oset only when this // function succees. - let vt = VThread::current().unwrap(); - let mut mask = vt.sigmask_mut(); + let mut mask = td.sigmask_mut(); let prev = *mask; // Update the mask. @@ -283,7 +284,7 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_sigaction(self: &Arc, i: &SysIn) -> Result { + fn sys_sigaction(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let sig: i32 = i.args[0].try_into().unwrap(); let act: *const SignalAct = i.args[1].into(); @@ -412,13 +413,13 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_thr_self(self: &Arc, i: &SysIn) -> Result { + fn sys_thr_self(self: &Arc, td: &VThread, i: &SysIn) -> Result { let id: *mut i64 = i.args[0].into(); - unsafe { *id = VThread::current().unwrap().id().get().into() }; + unsafe { *id = td.id().get().into() }; Ok(SysOut::ZERO) } - fn sys_thr_set_name(self: &Arc, i: &SysIn) -> Result { + fn sys_thr_set_name(self: &Arc, td: &VThread, i: &SysIn) -> Result { let tid: i32 = i.args[0].try_into().unwrap(); let name: Option<&str> = unsafe { i.args[1].to_str(32) }?; @@ -446,12 +447,11 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_rtprio_thread(self: &Arc, i: &SysIn) -> Result { + fn sys_rtprio_thread(self: &Arc, td: &VThread, i: &SysIn) -> Result { const RTP_LOOKUP: i32 = 0; const RTP_SET: i32 = 1; const RTP_UNK: i32 = 2; - let td = VThread::current().unwrap(); let function: i32 = i.args[0].try_into().unwrap(); let lwpid: i32 = i.args[1].try_into().unwrap(); let rtp: *mut RtPrio = i.args[2].into(); @@ -478,7 +478,7 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_cpuset_getaffinity(self: &Arc, i: &SysIn) -> Result { + fn sys_cpuset_getaffinity(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let level: i32 = i.args[0].try_into().unwrap(); let which: i32 = i.args[1].try_into().unwrap(); @@ -548,12 +548,12 @@ impl VProc { } } - fn sys_is_in_sandbox(self: &Arc, _: &SysIn) -> Result { + fn sys_is_in_sandbox(self: &Arc, _: &VThread, _: &SysIn) -> Result { // TODO: Implement this once FS rework has been usable. Ok(1.into()) } - fn sys_get_authinfo(self: &Arc, i: &SysIn) -> Result { + fn sys_get_authinfo(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let pid: i32 = i.args[0].try_into().unwrap(); let buf: *mut AuthInfo = i.args[1].into(); @@ -565,7 +565,6 @@ impl VProc { // Check privilege. let mut info: AuthInfo = unsafe { zeroed() }; - let td = VThread::current().unwrap(); if td.priv_check(Privilege::SCE686).is_ok() { info = self.cred.auth().clone(); @@ -591,7 +590,7 @@ impl VProc { Ok(SysOut::ZERO) } - fn sys_randomized_path(self: &Arc, i: &SysIn) -> Result { + fn sys_randomized_path(self: &Arc, _: &VThread, i: &SysIn) -> Result { let set = i.args[0]; let get: *mut c_char = i.args[1].into(); let len: *mut usize = i.args[2].into(); diff --git a/src/kernel/src/regmgr/mod.rs b/src/kernel/src/regmgr/mod.rs index de79fa0ef..4679837d4 100644 --- a/src/kernel/src/regmgr/mod.rs +++ b/src/kernel/src/regmgr/mod.rs @@ -27,7 +27,7 @@ impl RegMgr { mgr } - fn sys_regmgr_call(self: &Arc, i: &SysIn) -> Result { + fn sys_regmgr_call(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let op: u32 = i.args[0].try_into().unwrap(); let buf: *mut i32 = i.args[2].into(); @@ -48,7 +48,6 @@ impl RegMgr { } // Execute the operation. - let td = VThread::current().unwrap(); let r = match op { 0x18 => { let v1 = unsafe { read::(req as _) }; @@ -333,7 +332,7 @@ impl RegMgr { None } - fn sys_workaround8849(self: &Arc, i: &SysIn) -> Result { + fn sys_workaround8849(self: &Arc, _: &VThread, i: &SysIn) -> Result { let key = { let arg: usize = i.args[0].into(); let key: u32 = arg.try_into().unwrap(); diff --git a/src/kernel/src/rtld/mod.rs b/src/kernel/src/rtld/mod.rs index d51efd321..58616fa46 100644 --- a/src/kernel/src/rtld/mod.rs +++ b/src/kernel/src/rtld/mod.rs @@ -381,7 +381,7 @@ impl RuntimeLinker { unsafe { String::from_utf8_unchecked(nid) } } - fn sys_dynlib_dlsym(self: &Arc, i: &SysIn) -> Result { + fn sys_dynlib_dlsym(self: &Arc, _: &VThread, i: &SysIn) -> Result { // Check if application is dynamic linking. if self.app.file_info().is_none() { return Err(SysErr::Raw(EPERM)); @@ -418,7 +418,7 @@ impl RuntimeLinker { Ok(SysOut::ZERO) } - fn sys_dynlib_get_list(self: &Arc, i: &SysIn) -> Result { + fn sys_dynlib_get_list(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let buf: *mut u32 = i.args[0].into(); let max: usize = i.args[1].into(); @@ -448,9 +448,8 @@ impl RuntimeLinker { Ok(SysOut::ZERO) } - fn sys_dynlib_load_prx(self: &Arc, i: &SysIn) -> Result { + fn sys_dynlib_load_prx(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Check if application is a dynamic SELF. - let td = VThread::current().unwrap(); if self.app.file_info().is_none() { return Err(SysErr::Raw(EPERM)); @@ -554,7 +553,11 @@ impl RuntimeLinker { Ok(SysOut::ZERO) } - fn sys_dynlib_do_copy_relocations(self: &Arc, _: &SysIn) -> Result { + fn sys_dynlib_do_copy_relocations( + self: &Arc, + _: &VThread, + _: &SysIn, + ) -> Result { if let Some(info) = self.app.file_info() { if info.relocs().any(|r| r.ty() == Relocation::R_X86_64_COPY) { return Err(SysErr::Raw(EINVAL)); @@ -566,7 +569,11 @@ impl RuntimeLinker { } } - fn sys_dynlib_get_proc_param(self: &Arc, i: &SysIn) -> Result { + fn sys_dynlib_get_proc_param( + self: &Arc, + _: &VThread, + i: &SysIn, + ) -> Result { // Get arguments. let param: *mut usize = i.args[0].into(); let size: *mut usize = i.args[1].into(); @@ -591,6 +598,7 @@ impl RuntimeLinker { fn sys_dynlib_process_needed_and_relocate( self: &Arc, + td: &VThread, _: &SysIn, ) -> Result { // Check if application is dynamic linking. @@ -874,7 +882,7 @@ impl RuntimeLinker { } } - fn sys_dynlib_get_info_ex(self: &Arc, i: &SysIn) -> Result { + fn sys_dynlib_get_info_ex(self: &Arc, _: &VThread, i: &SysIn) -> Result { // Get arguments. let handle: u32 = i.args[0].try_into().unwrap(); let flags: u32 = i.args[1].try_into().unwrap(); @@ -994,7 +1002,11 @@ impl RuntimeLinker { Ok(SysOut::ZERO) } - fn sys_dynlib_get_obj_member(self: &Arc, i: &SysIn) -> Result { + fn sys_dynlib_get_obj_member( + self: &Arc, + _: &VThread, + i: &SysIn, + ) -> Result { let handle: u32 = i.args[0].try_into().unwrap(); let ty: u8 = i.args[1].try_into().unwrap(); let out: *mut usize = i.args[2].into(); diff --git a/src/kernel/src/shm/mod.rs b/src/kernel/src/shm/mod.rs index 20de5a156..e23b0825d 100644 --- a/src/kernel/src/shm/mod.rs +++ b/src/kernel/src/shm/mod.rs @@ -27,7 +27,7 @@ impl SharedMemoryManager { shm } - fn sys_shm_open(self: &Arc, i: &SysIn) -> Result { + fn sys_shm_open(self: &Arc, td: &VThread, i: &SysIn) -> Result { let path = unsafe { i.args[0].to_shm_path() }?.expect("invalid shm path"); let flags: OpenFlags = i.args[1].try_into().unwrap(); let mode: u32 = i.args[2].try_into().unwrap(); @@ -47,8 +47,6 @@ impl SharedMemoryManager { return Err(SysErr::Raw(EINVAL)); } - let td = VThread::current().unwrap(); - let filedesc = td.proc().files(); let mode = mode & filedesc.cmask() & 0o7777; @@ -68,7 +66,7 @@ impl SharedMemoryManager { Ok(fd.into()) } - fn sys_shm_unlink(self: &Arc, i: &SysIn) -> Result { + fn sys_shm_unlink(self: &Arc, td: &VThread, i: &SysIn) -> Result { todo!("sys_shm_unlink") } } diff --git a/src/kernel/src/syscalls/mod.rs b/src/kernel/src/syscalls/mod.rs index b7e3ce581..014fb32c0 100644 --- a/src/kernel/src/syscalls/mod.rs +++ b/src/kernel/src/syscalls/mod.rs @@ -1,12 +1,13 @@ -pub use self::error::*; -pub use self::input::*; -pub use self::output::*; - use crate::errno::ENOSYS; +use crate::process::VThread; use crate::warn; use std::fmt::{Debug, Formatter}; use std::sync::Arc; +pub use self::error::*; +pub use self::input::*; +pub use self::output::*; + mod error; mod input; mod output; @@ -16,7 +17,7 @@ pub struct Syscalls { handlers: [Option; 678], } -type SyscallHandler = Box Result + Send + Sync>; +type SyscallHandler = Box Result + Send + Sync>; impl Syscalls { pub fn new() -> Self { @@ -34,12 +35,12 @@ impl Syscalls { &mut self, id: u32, o: &Arc, - h: fn(&Arc, &SysIn) -> Result, + handler: fn(&Arc, &VThread, &SysIn) -> Result, ) { let o = o.clone(); assert!(self.handlers[id as usize] - .replace(Box::new(move |i| h(&o, i))) + .replace(Box::new(move |td, i| handler(&o, td, i))) .is_none()); } @@ -53,27 +54,27 @@ impl Syscalls { // // See https://github.com/freebsd/freebsd-src/blob/release/9.1.0/sys/kern/init_sysent.c#L36 // for standard FreeBSD syscalls. - let h = match self.handlers.get(i.id as usize) { - Some(v) => match v { - Some(v) => v, - None => todo!( - "syscall {} at {:#x} on {} with args = ({:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:#x})", - i.id, - i.offset, - i.module, - i.args[0], - i.args[1], - i.args[2], - i.args[3], - i.args[4], - i.args[5], - ), - }, + let handler = match self.handlers.get(i.id as usize) { + Some(Some(v)) => v, + Some(None) => todo!( + "syscall {} at {:#x} on {} with args = ({:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:#x})", + i.id, + i.offset, + i.module, + i.args[0], + i.args[1], + i.args[2], + i.args[3], + i.args[4], + i.args[5], + ), None => return ENOSYS.get().into(), }; + let td = VThread::current().expect("Syscall invoked outside of a PS4 thread context"); + // Execute the handler. - let v = match h(i) { + let v = match handler(&td, i) { Ok(v) => v, Err(e) => { warn!(e, "Syscall {} failed", i.id); diff --git a/src/kernel/src/sysctl/mod.rs b/src/kernel/src/sysctl/mod.rs index 469af996a..4d6c22c3e 100644 --- a/src/kernel/src/sysctl/mod.rs +++ b/src/kernel/src/sysctl/mod.rs @@ -110,7 +110,7 @@ impl Sysctl { ctl } - fn sys_sysctl(self: &Arc, i: &SysIn) -> Result { + fn sys_sysctl(self: &Arc, td: &VThread, i: &SysIn) -> Result { // Get arguments. let name: *const i32 = i.args[0].into(); let namelen: u32 = i.args[1].try_into().unwrap(); @@ -128,8 +128,6 @@ impl Sysctl { unsafe { std::slice::from_raw_parts(name, namelen as _) } }; - let td = VThread::current().unwrap(); - if name[0] == Self::CTL_DEBUG && !td.proc().cred().is_system() { return Err(SysErr::Raw(EINVAL)); } @@ -396,10 +394,7 @@ impl Sysctl { req.write(&td.proc().ptc().to_ne_bytes())?; td.proc().uptc().store( - req.old - .as_mut() - .map(|v| v.as_mut_ptr()) - .unwrap_or(null_mut()), + req.old.as_mut().map_or(null_mut(), |v| v.as_mut_ptr()), Ordering::Relaxed, ); diff --git a/src/kernel/src/time/mod.rs b/src/kernel/src/time/mod.rs index 0197c1d00..cb79ffb88 100644 --- a/src/kernel/src/time/mod.rs +++ b/src/kernel/src/time/mod.rs @@ -1,4 +1,5 @@ use crate::errno::Errno; +use crate::process::VThread; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use std::num::NonZeroI32; use std::sync::Arc; @@ -16,7 +17,7 @@ impl TimeManager { time } - pub fn sys_gettimeofday(self: &Arc, i: &SysIn) -> Result { + pub fn sys_gettimeofday(self: &Arc, _: &VThread, i: &SysIn) -> Result { let tv: *mut TimeVal = i.args[0].into(); let tz: *mut TimeZone = i.args[1].into(); @@ -33,7 +34,7 @@ impl TimeManager { Ok(SysOut::ZERO) } - pub fn sys_clock_gettime(self: &Arc, i: &SysIn) -> Result { + pub fn sys_clock_gettime(self: &Arc, _: &VThread, i: &SysIn) -> Result { let clock: i32 = i.args[0].try_into().unwrap(); todo!("clock_gettime with clock = {clock}") From c84b2fac6b4075824f0dcdbbca7e4e68d4a3938d Mon Sep 17 00:00:00 2001 From: SuchAFuriousDeath <48620541+SuchAFuriousDeath@users.noreply.github.com> Date: Fri, 23 Feb 2024 00:05:04 +0100 Subject: [PATCH 4/4] Makes FileSystem::root fallible, makes vnode item an enum (#678) --- src/kernel/src/fs/dev/mod.rs | 10 +++--- src/kernel/src/fs/dev/vnode.rs | 10 ++++-- src/kernel/src/fs/host/mod.rs | 15 +++++++-- src/kernel/src/fs/mod.rs | 60 +++++++++++++++++++-------------- src/kernel/src/fs/mount.rs | 5 +-- src/kernel/src/fs/null/mod.rs | 6 ++-- src/kernel/src/fs/null/vnode.rs | 16 +++++++-- src/kernel/src/fs/tmp/mod.rs | 35 ++++++++++++------- src/kernel/src/fs/tmp/node.rs | 51 ++++++++++++++++++++++++++++ src/kernel/src/fs/vnode.rs | 29 +++++++++------- src/kernel/src/main.rs | 4 +-- 11 files changed, 174 insertions(+), 67 deletions(-) diff --git a/src/kernel/src/fs/dev/mod.rs b/src/kernel/src/fs/dev/mod.rs index e6fa1bab6..9cf72ab1d 100644 --- a/src/kernel/src/fs/dev/mod.rs +++ b/src/kernel/src/fs/dev/mod.rs @@ -3,7 +3,7 @@ use self::dirent::Dirent; use self::vnode::VnodeBackend; use super::{ path_contains, DirentType, Filesystem, FsConfig, Mode, Mount, MountFlags, MountOpts, - MountSource, VPathBuf, Vnode, VnodeType, + MountSource, VPathBuf, Vnode, VnodeItem, VnodeType, }; use crate::errno::{Errno, EEXIST, ENOENT, EOPNOTSUPP}; use crate::ucred::{Gid, Ucred, Uid}; @@ -105,7 +105,7 @@ fn alloc_vnode( .ok_or(AllocVnodeError::DeviceGone)?; let vn = Vnode::new(mnt, VnodeType::Character, tag, backend); - *vn.item_mut() = Some(dev); + *vn.item_mut() = Some(VnodeItem::Device(dev)); vn } DirentType::Directory => Vnode::new( @@ -358,10 +358,12 @@ pub fn mount( } impl Filesystem for DevFs { - fn root(self: Arc, mnt: &Arc) -> Arc { + fn root(self: Arc, mnt: &Arc) -> Result, Box> { let ent = self.root.clone(); - alloc_vnode(self, mnt, ent).unwrap() + let vnode = alloc_vnode(self, mnt, ent)?; + + Ok(vnode) } } diff --git a/src/kernel/src/fs/dev/vnode.rs b/src/kernel/src/fs/dev/vnode.rs index 0e38d3eae..926c3b3f9 100644 --- a/src/kernel/src/fs/dev/vnode.rs +++ b/src/kernel/src/fs/dev/vnode.rs @@ -1,8 +1,9 @@ use super::dirent::Dirent; -use super::{alloc_vnode, AllocVnodeError, Cdev, DevFs}; +use super::{alloc_vnode, AllocVnodeError, DevFs}; use crate::errno::{Errno, EIO, ENOENT, ENOTDIR, ENXIO}; use crate::fs::{ - check_access, Access, IoCmd, OpenFlags, RevokeFlags, VFile, Vnode, VnodeAttrs, VnodeType, + check_access, Access, IoCmd, OpenFlags, RevokeFlags, VFile, Vnode, VnodeAttrs, VnodeItem, + VnodeType, }; use crate::process::VThread; use macros::Errno; @@ -175,7 +176,10 @@ impl crate::fs::VnodeBackend for VnodeBackend { } // Not sure why FreeBSD check if vnode is VBLK because all of vnode here always be VCHR. - let dev = vn.item().unwrap().downcast::().unwrap(); + let item = vn.item(); + let Some(VnodeItem::Device(dev)) = item.as_ref() else { + unreachable!(); + }; let sw = dev.sw(); if file.is_none() && sw.fdopen().is_some() { diff --git a/src/kernel/src/fs/host/mod.rs b/src/kernel/src/fs/host/mod.rs index e367835be..3152f88b2 100644 --- a/src/kernel/src/fs/host/mod.rs +++ b/src/kernel/src/fs/host/mod.rs @@ -9,6 +9,7 @@ use param::Param; use std::collections::HashMap; use std::fs::create_dir; use std::io::ErrorKind; +use std::num::NonZeroI32; use std::path::{Path, PathBuf}; use std::sync::{Arc, Weak}; use thiserror::Error; @@ -114,8 +115,10 @@ pub fn mount( } impl Filesystem for HostFs { - fn root(self: Arc, mnt: &Arc) -> Arc { - get_vnode(&self, mnt, None).unwrap() + fn root(self: Arc, mnt: &Arc) -> Result, Box> { + let vnode = get_vnode(&self, mnt, None)?; + + Ok(vnode) } } @@ -146,7 +149,7 @@ fn get_vnode( // Get vnode type. let ty = match file.is_directory() { Ok(true) => VnodeType::Directory(path == fs.root), - Ok(false) => todo!(), + Ok(false) => VnodeType::File, Err(e) => return Err(GetVnodeError::GetFileTypeFailed(e)), }; @@ -182,3 +185,9 @@ enum GetVnodeError { #[error("cannot determine file type")] GetFileTypeFailed(#[source] std::io::Error), } + +impl Errno for GetVnodeError { + fn errno(&self) -> NonZeroI32 { + todo!() + } +} diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index 2cb933330..cf7f18820 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -12,7 +12,7 @@ use param::Param; use std::fmt::{Display, Formatter}; use std::num::{NonZeroI32, TryFromIntError}; use std::path::PathBuf; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use thiserror::Error; pub use self::dev::{make_dev, Cdev, CdevSw, DriverFlags, MakeDev, MakeDevError}; @@ -53,7 +53,7 @@ impl Fs { param: &Arc, kern_cred: &Arc, sys: &mut Syscalls, - ) -> Result, FsError> { + ) -> Result, FsInitError> { // Mount devfs as an initial root. let mut mounts = Mounts::new(); let conf = Self::find_config("devfs").unwrap(); @@ -65,11 +65,11 @@ impl Fs { MountOpts::new(), MountFlags::empty(), ) - .map_err(FsError::MountDevFailed)?; + .map_err(FsInitError::MountDevFailed)?; // Get an initial root vnode. let init = mounts.push(init); - let root = init.root(); + let root = init.root().map_err(FsInitError::GetDevRootFailed)?; // Setup mount options for root FS. let mut opts = MountOpts::new(); @@ -92,7 +92,7 @@ impl Fs { let root = fs .mount(opts, MountFlags::MNT_ROOTFS, None) - .map_err(FsError::MountRootFailed)?; + .map_err(FsInitError::MountRootFailed)?; // Swap devfs with rootfs so rootfs become an actual root. let old = { @@ -106,13 +106,13 @@ impl Fs { }; // Disconnect rootfs from the root of devfs. - *old.root().item_mut() = None; + *old.root().map_err(FsInitError::GetRootFailed)?.item_mut() = None; *fs.mounts.read().root().parent_mut() = None; // Set devfs parent to /dev on the root FS. let dev = fs .lookup(vpath!("/dev"), None) - .map_err(FsError::LookupDevFailed)?; + .map_err(FsInitError::LookupDevFailed)?; assert!(dev.is_directory()); @@ -125,7 +125,7 @@ impl Fs { { let mut i = dev.item_mut(); assert!(i.is_none()); - *i = Some(Arc::new(Arc::downgrade(&old))); + *i = Some(VnodeItem::Mount(Arc::downgrade(&old))); } // Install syscall handlers. @@ -195,20 +195,18 @@ impl Fs { // TODO: Handle link. let mut item = root.item_mut(); - match item - .as_ref() - .map(|i| i.downcast_ref::>().unwrap()) - { - Some(m) => match m.upgrade() { + match item.as_ref() { + Some(VnodeItem::Mount(m)) => match m.upgrade() { Some(m) => { drop(item); - root = m.root(); + root = m.root().map_err(LookupError::GetRootFailed)?; } None => { *item = None; drop(item); } }, + Some(_) => unreachable!(), None => drop(item), } @@ -219,20 +217,18 @@ impl Fs { VnodeType::Directory(_) => { let mut item = vn.item_mut(); - match item - .as_ref() - .map(|i| i.downcast_ref::>().unwrap()) - { - Some(m) => match m.upgrade() { + match item.as_ref() { + Some(VnodeItem::Mount(m)) => match m.upgrade() { Some(m) => { drop(item); - vn = m.root(); + vn = m.root().map_err(LookupError::GetRootFailed)?; } None => { *item = None; drop(item); } }, + Some(_) => unreachable!(), None => drop(item), } } @@ -321,7 +317,7 @@ impl Fs { _ => return true, } - return false; + false }); if fs.len() >= 15 { @@ -367,11 +363,11 @@ impl Fs { return Err(MountError::PathAlreadyMounted); } - *item = Some(Arc::new(Arc::downgrade(&mount))); + *item = Some(VnodeItem::Mount(Arc::downgrade(&mount))); drop(item); // TODO: Implement the remaining logics from the PS4. - Ok(mount.root()) + Ok(mount.root().map_err(MountError::GetRootFailed)?) } } @@ -1077,12 +1073,18 @@ impl TryFrom for TruncateLength { } pub struct TruncateLengthError(()); -/// Represents an error when FS was failed to initialized. +/// Represents an error when FS fails to initialize. #[derive(Debug, Error)] -pub enum FsError { +pub enum FsInitError { #[error("cannot mount devfs")] MountDevFailed(#[source] Box), + #[error("cannot get devfs root vnode")] + GetDevRootFailed(#[source] Box), + + #[error("cannot get root mount vnode")] + GetRootFailed(#[source] Box), + #[error("cannot mount rootfs")] MountRootFailed(#[source] MountError), @@ -1110,6 +1112,9 @@ pub enum MountError { #[error("fspath is already mounted")] PathAlreadyMounted, + + #[error("cannot get root")] + GetRootFailed(#[source] Box), } impl Errno for MountError { @@ -1120,6 +1125,7 @@ impl Errno for MountError { Self::LookupPathFailed(e) => e.errno(), Self::MountFailed(e) => e.errno(), Self::PathAlreadyMounted => EBUSY, + Self::GetRootFailed(e) => e.errno(), } } } @@ -1173,6 +1179,9 @@ impl Errno for IoctlError { /// Represents an error when [`Fs::lookup()`] fails. #[derive(Debug, Error)] pub enum LookupError { + #[error("failed to get mount root")] + GetRootFailed(#[source] Box), + #[error("no such file or directory")] NotFound, @@ -1183,6 +1192,7 @@ pub enum LookupError { impl Errno for LookupError { fn errno(&self) -> NonZeroI32 { match self { + Self::GetRootFailed(e) => e.errno(), Self::NotFound => ENOENT, Self::LookupFailed(_, _, e) => e.errno(), } diff --git a/src/kernel/src/fs/mount.rs b/src/kernel/src/fs/mount.rs index 5ab1f50d0..241c56b35 100644 --- a/src/kernel/src/fs/mount.rs +++ b/src/kernel/src/fs/mount.rs @@ -1,4 +1,5 @@ use super::{FsConfig, Mode, VPathBuf, Vnode}; +use crate::errno::Errno; use crate::ucred::{Gid, Ucred, Uid}; use bitflags::bitflags; use macros::EnumConversions; @@ -115,7 +116,7 @@ impl Mount { self.parent.write().unwrap() } - pub fn root(self: &Arc) -> Arc { + pub fn root(self: &Arc) -> Result, Box> { self.fs.clone().root(self) } @@ -129,7 +130,7 @@ impl Mount { /// Our version is a bit different from FreeBSD. We moved `vfs_mount` into `vfsconf` and we merge it /// with `mnt_data`. pub(super) trait Filesystem: Debug + Send + Sync { - fn root(self: Arc, mnt: &Arc) -> Arc; // vfs_root + fn root(self: Arc, mnt: &Arc) -> Result, Box>; // vfs_root } bitflags! { diff --git a/src/kernel/src/fs/null/mod.rs b/src/kernel/src/fs/null/mod.rs index bcd4af32f..65b788302 100644 --- a/src/kernel/src/fs/null/mod.rs +++ b/src/kernel/src/fs/null/mod.rs @@ -21,8 +21,10 @@ impl NullFs { } impl Filesystem for NullFs { - fn root(self: Arc, mnt: &Arc) -> Arc { - null_nodeget(mnt, self.lower.clone()) + fn root(self: Arc, mnt: &Arc) -> Result, Box> { + let vnode = null_nodeget(mnt, self.lower.clone())?; + + Ok(vnode) } } diff --git a/src/kernel/src/fs/null/vnode.rs b/src/kernel/src/fs/null/vnode.rs index bc8f092b4..3cc72b117 100644 --- a/src/kernel/src/fs/null/vnode.rs +++ b/src/kernel/src/fs/null/vnode.rs @@ -65,7 +65,7 @@ impl crate::fs::VnodeBackend for VnodeBackend { let vnode = if Arc::ptr_eq(&lower, vn) { vn.clone() } else { - null_nodeget(vn.fs(), lower) + null_nodeget(vn.fs(), lower)? }; Ok(vnode) @@ -152,6 +152,18 @@ impl Errno for OpenError { } /// See `null_nodeget` on the PS4 for a reference. -pub(super) fn null_nodeget(mnt: &Arc, lower: Arc) -> Arc { +pub(super) fn null_nodeget( + mnt: &Arc, + lower: Arc, +) -> Result, NodeGetError> { todo!() } + +#[derive(Debug, Error)] +pub(super) enum NodeGetError {} + +impl Errno for NodeGetError { + fn errno(&self) -> NonZeroI32 { + todo!() + } +} diff --git a/src/kernel/src/fs/tmp/mod.rs b/src/kernel/src/fs/tmp/mod.rs index 80c72e4b8..2eafc6c55 100644 --- a/src/kernel/src/fs/tmp/mod.rs +++ b/src/kernel/src/fs/tmp/mod.rs @@ -22,11 +22,10 @@ pub fn mount( return Err(Box::new(MountError::UpdateNotSupported)); } + let parent = parent.expect("Parent vnode has to be provided to tmpfs"); + // Get mount point attributes. - let attrs = match parent.as_ref().unwrap().getattr() { - Ok(v) => v, - Err(e) => return Err(Box::new(MountError::GetParentAttrsFailed(e))), - }; + let attrs = parent.getattr().map_err(MountError::GetParentAttrsFailed)?; // Get GID. let gid = if cred.real_uid() == Uid::ROOT { @@ -77,17 +76,14 @@ pub fn mount( }); // Allocate a root node. - let root = match nodes.alloc() { - Ok(v) => v, - Err(e) => return Err(Box::new(MountError::AllocRootFailed(e))), - }; + let root = nodes.alloc()?; Ok(Mount::new( conf, cred, MountSource::Driver("tmpfs"), path, - parent, + Some(parent), flags | MountFlags::MNT_LOCAL, TempFs { max_pages: pages, @@ -110,11 +106,17 @@ struct TempFs { } impl Filesystem for TempFs { - fn root(self: Arc, mnt: &Arc) -> Arc { - todo!() + fn root(self: Arc, mnt: &Arc) -> Result, Box> { + let vnode = alloc_vnode(mnt, &self.root)?; + + Ok(vnode) } } +fn alloc_vnode(mnt: &Arc, node: &Arc) -> Result, AllocVnodeError> { + todo!() +} + /// Represents an error when [`mount()`] fails. #[derive(Debug, Error)] enum MountError { @@ -125,7 +127,7 @@ enum MountError { GetParentAttrsFailed(#[source] Box), #[error("cannot allocate a root node")] - AllocRootFailed(#[source] AllocNodeError), + AllocRootFailed(#[from] AllocNodeError), } impl Errno for MountError { @@ -137,3 +139,12 @@ impl Errno for MountError { } } } + +#[derive(Debug, Error)] +enum AllocVnodeError {} + +impl Errno for AllocVnodeError { + fn errno(&self) -> NonZeroI32 { + todo!() + } +} diff --git a/src/kernel/src/fs/tmp/node.rs b/src/kernel/src/fs/tmp/node.rs index 729e12378..414da9cad 100644 --- a/src/kernel/src/fs/tmp/node.rs +++ b/src/kernel/src/fs/tmp/node.rs @@ -1,4 +1,6 @@ use crate::errno::{Errno, ENOSPC}; +use crate::fs::{Access, OpenFlags, VFile, Vnode, VnodeAttrs, VnodeBackend}; +use crate::process::VThread; use macros::Errno; use std::collections::VecDeque; use std::sync::{Arc, RwLock}; @@ -41,6 +43,55 @@ impl Nodes { #[derive(Debug)] pub struct Node {} +impl VnodeBackend for Node { + #[allow(unused_variables)] // TODO: remove when implementing + fn access( + self: Arc, + vn: &Arc, + td: Option<&VThread>, + mode: Access, + ) -> Result<(), Box> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn getattr(self: Arc, vn: &Arc) -> Result> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn lookup( + self: Arc, + vn: &Arc, + td: Option<&VThread>, + name: &str, + ) -> Result, Box> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn mkdir( + self: Arc, + parent: &Arc, + name: &str, + mode: u32, + td: Option<&VThread>, + ) -> Result, Box> { + todo!() + } + + #[allow(unused_variables)] // TODO: remove when implementing + fn open( + self: Arc, + vn: &Arc, + td: Option<&VThread>, + mode: OpenFlags, + #[allow(unused_variables)] file: Option<&mut VFile>, + ) -> Result<(), Box> { + todo!() + } +} + /// Represents an error when [`Nodes::alloc()`] fails. #[derive(Debug, Error, Errno)] pub enum AllocNodeError { diff --git a/src/kernel/src/fs/vnode.rs b/src/kernel/src/fs/vnode.rs index 94e3c5d01..61ce19c49 100644 --- a/src/kernel/src/fs/vnode.rs +++ b/src/kernel/src/fs/vnode.rs @@ -1,16 +1,15 @@ use super::{ - unixify_access, Access, FileBackend, IoCmd, Mode, Mount, OpenFlags, RevokeFlags, Stat, + unixify_access, Access, Cdev, FileBackend, IoCmd, Mode, Mount, OpenFlags, RevokeFlags, Stat, TruncateLength, Uio, UioMut, VFile, }; use crate::errno::{Errno, ENOTDIR, ENOTTY, EOPNOTSUPP, EPERM}; use crate::process::VThread; use crate::ucred::{Gid, Uid}; -use gmtx::{Gutex, GutexGroup, GutexWriteGuard}; +use gmtx::{Gutex, GutexGroup, GutexReadGuard, GutexWriteGuard}; use macros::Errno; -use std::any::Any; use std::fmt::Debug; use std::sync::atomic::{AtomicUsize, Ordering}; -use std::sync::Arc; +use std::sync::{Arc, Weak}; use thiserror::Error; /// An implementation of `vnode`. @@ -20,11 +19,11 @@ use thiserror::Error; /// file/directory have only one vnode. #[derive(Debug)] pub struct Vnode { - fs: Arc, // v_mount - ty: VnodeType, // v_type - tag: &'static str, // v_tag - backend: Arc, // v_op + v_data - item: Gutex>>, // v_un + fs: Arc, // v_mount + ty: VnodeType, // v_type + tag: &'static str, // v_tag + backend: Arc, // v_op + v_data + item: Gutex>, // v_un } impl Vnode { @@ -64,11 +63,11 @@ impl Vnode { matches!(self.ty, VnodeType::Character) } - pub fn item(&self) -> Option> { - self.item.read().clone() + pub fn item(&self) -> GutexReadGuard> { + self.item.read() } - pub fn item_mut(&self) -> GutexWriteGuard>> { + pub fn item_mut(&self) -> GutexWriteGuard> { self.item.write() } @@ -176,6 +175,12 @@ impl Drop for Vnode { } } +#[derive(Debug, Clone)] +pub enum VnodeItem { + Mount(Weak), + Device(Arc), +} + /// An implementation of `vtype`. #[derive(Debug, Clone)] pub enum VnodeType { diff --git a/src/kernel/src/main.rs b/src/kernel/src/main.rs index a5f31f238..cb0d510fd 100644 --- a/src/kernel/src/main.rs +++ b/src/kernel/src/main.rs @@ -3,7 +3,7 @@ use crate::budget::{Budget, BudgetManager, ProcType}; use crate::debug::{DebugManager, DebugManagerInitError}; use crate::dmem::DmemManager; use crate::ee::{EntryArg, RawFn}; -use crate::fs::{Fs, FsError, MountError, MountFlags, MountOpts, VPath}; +use crate::fs::{Fs, FsInitError, MountError, MountFlags, MountOpts, VPath}; use crate::kqueue::KernelQueueManager; use crate::llvm::Llvm; use crate::log::{print, LOGGER}; @@ -519,7 +519,7 @@ enum KernelError { InvalidTitleId(PathBuf), #[error("filesystem initialization failed")] - FilesystemInitFailed(#[from] FsError), + FilesystemInitFailed(#[from] FsInitError), #[error("couldn't mount {0}")] MountFailed(&'static VPath, #[source] MountError),