From 2536eba7383ef88a028102d68cc5d6c0febe7340 Mon Sep 17 00:00:00 2001 From: Putta Khunchalee Date: Sun, 21 Apr 2024 17:49:22 +0700 Subject: [PATCH] Removes VFileType --- .vscode/settings.json | 1 + src/kernel/src/dmem/blockpool.rs | 7 ++- src/kernel/src/dmem/mod.rs | 18 +++---- src/kernel/src/fs/dev/cdev.rs | 17 +++++-- src/kernel/src/fs/dev/vnode.rs | 2 +- src/kernel/src/fs/file.rs | 65 ++++++++++++------------ src/kernel/src/fs/mod.rs | 2 +- src/kernel/src/fs/vnode.rs | 8 +-- src/kernel/src/kqueue/mod.rs | 8 +-- src/kernel/src/net/mod.rs | 80 +++++++++--------------------- src/kernel/src/net/socket.rs | 24 +++++++-- src/kernel/src/process/filedesc.rs | 28 +---------- src/kernel/src/shm/mod.rs | 7 ++- 13 files changed, 125 insertions(+), 142 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 540ca444e..1622798f3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "settings set target.x86-disassembly-flavor intel" ], "rust-analyzer.imports.granularity.group": "module", + "rust-analyzer.imports.group.enable": false, "[rust]": { "editor.formatOnSave": true } diff --git a/src/kernel/src/dmem/blockpool.rs b/src/kernel/src/dmem/blockpool.rs index 690d90990..727582898 100644 --- a/src/kernel/src/dmem/blockpool.rs +++ b/src/kernel/src/dmem/blockpool.rs @@ -1,6 +1,7 @@ use crate::errno::Errno; -use crate::fs::{DefaultFileBackendError, FileBackend, IoCmd, PollEvents, Stat, VFile}; +use crate::fs::{DefaultFileBackendError, FileBackend, IoCmd, PollEvents, Stat, VFile, Vnode}; use crate::process::VThread; +use std::sync::Arc; #[derive(Debug)] pub struct BlockPool {} @@ -38,6 +39,10 @@ impl FileBackend for BlockPool { todo!() } + + fn vnode(&self) -> Option<&Arc> { + None + } } #[repr(C)] diff --git a/src/kernel/src/dmem/mod.rs b/src/kernel/src/dmem/mod.rs index 5da253207..03d86ed0e 100644 --- a/src/kernel/src/dmem/mod.rs +++ b/src/kernel/src/dmem/mod.rs @@ -1,8 +1,8 @@ +use self::blockpool::BlockPool; use crate::dev::{Dmem, DmemContainer}; use crate::errno::EINVAL; use crate::fs::{ - make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode, VFile, - VFileFlags, VFileType, + make_dev, CharacterDevice, DriverFlags, Fs, MakeDevError, MakeDevFlags, Mode, VFile, VFileFlags, }; use crate::info; use crate::process::VThread; @@ -12,7 +12,7 @@ use std::ops::Index; use std::sync::Arc; use thiserror::Error; -pub use self::blockpool::*; +pub use self::blockpool::{BlockpoolExpandArgs, BlockpoolStats}; mod blockpool; @@ -134,15 +134,11 @@ impl DmemManager { } let bp = BlockPool::new(); - let flags = VFileFlags::from_bits_retain(flags) | VFileFlags::WRITE; - - let fd = td.proc().files().alloc(Arc::new(VFile::new( - VFileType::Blockpool, - flags, - None, - Box::new(bp), - ))); + let fd = td + .proc() + .files() + .alloc(Arc::new(VFile::new(flags, Box::new(bp)))); info!("Opened a blockpool at fd = {fd}"); diff --git a/src/kernel/src/fs/dev/cdev.rs b/src/kernel/src/fs/dev/cdev.rs index 6bca8b5d1..a09c1b1e7 100644 --- a/src/kernel/src/fs/dev/cdev.rs +++ b/src/kernel/src/fs/dev/cdev.rs @@ -2,7 +2,7 @@ use super::dirent::Dirent; use crate::errno::{Errno, ENODEV, ENOTTY}; use crate::fs::{ FileBackend, IoCmd, IoLen, IoVec, IoVecMut, Mode, OpenFlags, PollEvents, Stat, TruncateLength, - VFile, + VFile, Vnode, }; use crate::process::VThread; use crate::time::TimeSpec; @@ -111,11 +111,14 @@ impl CharacterDevice { /// Implementation of `devfs_ops_f`. #[derive(Debug)] -pub(super) struct CdevFileBackend(Arc); +pub(super) struct CdevFileBackend { + vnode: Arc, + dev: Arc, +} impl CdevFileBackend { - pub fn new(dev: Arc) -> Self { - Self(dev) + pub fn new(vnode: Arc, dev: Arc) -> Self { + Self { vnode, dev } } } @@ -148,7 +151,7 @@ impl FileBackend for CdevFileBackend { match cmd { IoCmd::FIODTYPE(_) => todo!(), IoCmd::FIODGNAME(_) => todo!(), - _ => self.0.driver.ioctl(&self.0, cmd, td)?, + _ => self.dev.driver.ioctl(&self.dev, cmd, td)?, } Ok(()) @@ -170,6 +173,10 @@ impl FileBackend for CdevFileBackend { ) -> Result<(), Box> { todo!() } + + fn vnode(&self) -> Option<&Arc> { + Some(&self.vnode) + } } bitflags! { diff --git a/src/kernel/src/fs/dev/vnode.rs b/src/kernel/src/fs/dev/vnode.rs index aac3169ef..990939dd5 100644 --- a/src/kernel/src/fs/dev/vnode.rs +++ b/src/kernel/src/fs/dev/vnode.rs @@ -196,7 +196,7 @@ impl crate::fs::VnodeBackend for VnodeBackend { fn to_file_backend(&self, vn: &Arc) -> Box { match vn.item().deref() { - Some(VnodeItem::Device(d)) => Box::new(CdevFileBackend::new(d.clone())), + Some(VnodeItem::Device(d)) => Box::new(CdevFileBackend::new(vn.clone(), d.clone())), _ => Box::new(VnodeFileBackend::new(vn.clone())), } } diff --git a/src/kernel/src/fs/file.rs b/src/kernel/src/fs/file.rs index 6b14cce98..38cacf186 100644 --- a/src/kernel/src/fs/file.rs +++ b/src/kernel/src/fs/file.rs @@ -5,6 +5,7 @@ use crate::process::VThread; use bitflags::bitflags; use gmtx::{Gutex, GutexGroup}; use macros::Errno; +use std::any::{Any, TypeId}; use std::fmt::Debug; use std::io::{ErrorKind, Read, Seek, SeekFrom}; use std::sync::Arc; @@ -13,35 +14,22 @@ use thiserror::Error; /// An implementation of `file` structure. #[derive(Debug)] pub struct VFile { - ty: VFileType, // f_type - flags: VFileFlags, // f_flag - vnode: Option>, // f_vnode - offset: Gutex, // f_offset + flags: VFileFlags, // f_flag + offset: Gutex, // f_offset backend: Box, } impl VFile { - pub fn new( - ty: VFileType, - flags: VFileFlags, - vnode: Option>, - backend: Box, - ) -> Self { + pub fn new(flags: VFileFlags, backend: Box) -> Self { let gg = GutexGroup::new(); Self { - ty, flags, - vnode, offset: gg.spawn(0), backend, } } - pub fn ty(&self) -> &VFileType { - &self.ty - } - pub fn flags(&self) -> VFileFlags { self.flags } @@ -51,7 +39,7 @@ impl VFile { } pub fn vnode(&self) -> Option<&Arc> { - self.vnode.as_ref() + self.backend.vnode() } pub fn ioctl(&self, cmd: IoCmd, td: Option<&VThread>) -> Result<(), Box> { @@ -69,6 +57,25 @@ impl VFile { ) -> Result<(), Box> { self.backend.truncate(self, length, td) } + + /// Gets the `f_data` associated with this file. + /// + /// File implementation should use this method to check if the file has expected type. This + /// method should be impossible for non-file implementation to call because it required an + /// implementation of [`FileBackend`], which should not exposed by the subsystem itself. This + /// also imply the other subsystems cannot call this method with the other subsystem + /// implementation. + pub fn backend(&self) -> Option<&T> { + // TODO: Use Any::downcast_ref() when https://github.com/rust-lang/rust/issues/65991 is + // stabilized. Our current implementation here is copied from Any::downcast_ref(). + let b = self.backend.as_ref(); + + if b.type_id() == TypeId::of::() { + Some(unsafe { &*(b as *const dyn FileBackend as *const T) }) + } else { + None + } + } } impl Seek for VFile { @@ -122,19 +129,6 @@ impl Read for VFile { } } -/// Type of [`VFile`]. -#[repr(i16)] -#[derive(Debug, Clone, Copy)] -pub enum VFileType { - Vnode = 1, // DTYPE_VNODE - Socket = 2, // DTYPE_SOCKET - KernelQueue = 5, // DTYPE_KQUEUE - SharedMemory = 8, // DTYPE_SHM - Device = 11, // DTYPE_DEV - IpcSocket = 15, // DTYPE_IPCSOCKET - Blockpool = 17, // DTYPE_BLOCKPOOL -} - bitflags! { /// Flags for [`VFile`]. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -145,7 +139,10 @@ bitflags! { } /// An implementation of `fileops` structure. -pub trait FileBackend: Debug + Send + Sync + 'static { +/// +/// The implementation is internal to the subsystem itself so it should not expose itself to the +/// outside. +pub trait FileBackend: Any + Debug + Send + Sync + 'static { /// Implementation of `fo_flags` with `DFLAG_SEEKABLE`. fn is_seekable(&self) -> bool; @@ -191,6 +188,12 @@ pub trait FileBackend: Debug + Send + Sync + 'static { ) -> Result<(), Box> { Err(Box::new(DefaultFileBackendError::TruncateNotSupported)) } + + /// Get a vnode associated with this file (if any). + /// + /// Usually this will be [`Some`] if the file was opened from a filesystem (e.g. `/dev/null`) + /// and [`None`] if the file is not living on the filesystem (e.g. kqueue). + fn vnode(&self) -> Option<&Arc>; } #[derive(Debug, Error, Errno)] diff --git a/src/kernel/src/fs/mod.rs b/src/kernel/src/fs/mod.rs index a14a301fd..e4a210abf 100644 --- a/src/kernel/src/fs/mod.rs +++ b/src/kernel/src/fs/mod.rs @@ -181,7 +181,7 @@ impl Fs { .map_err(OpenError::LookupFailed)?; let backend = vnode.to_file_backend(); - Ok(VFile::new(VFileType::Vnode, flags, Some(vnode), backend)) + Ok(VFile::new(flags, backend)) } pub fn lookup( diff --git a/src/kernel/src/fs/vnode.rs b/src/kernel/src/fs/vnode.rs index f904d2ced..cf3a16ae9 100644 --- a/src/kernel/src/fs/vnode.rs +++ b/src/kernel/src/fs/vnode.rs @@ -2,7 +2,6 @@ use super::{ unixify_access, Access, CharacterDevice, FileBackend, IoCmd, IoLen, IoVec, IoVecMut, Mode, Mount, PollEvents, RevokeFlags, Stat, TruncateLength, VFile, }; -use crate::arnd; use crate::errno::{Errno, ENOTDIR, ENOTTY, EOPNOTSUPP, EPERM}; use crate::process::VThread; use crate::ucred::{Gid, Uid}; @@ -47,8 +46,7 @@ impl Vnode { backend: Box::new(backend), hash: { let mut buf = [0u8; 4]; - arnd::rand_bytes(&mut buf); - + crate::arnd::rand_bytes(&mut buf); u32::from_ne_bytes(buf) }, item: gg.spawn(None), @@ -344,6 +342,10 @@ impl FileBackend for VnodeFileBackend { ) -> Result<(), Box> { todo!() } + + fn vnode(&self) -> Option<&Arc> { + Some(&self.0) + } } /// Represents an error when default implementation of [`VnodeBackend`] fails. diff --git a/src/kernel/src/kqueue/mod.rs b/src/kernel/src/kqueue/mod.rs index 870df5363..a5e973efb 100644 --- a/src/kernel/src/kqueue/mod.rs +++ b/src/kernel/src/kqueue/mod.rs @@ -1,7 +1,7 @@ use crate::budget::BudgetType; use crate::errno::Errno; use crate::fs::{ - DefaultFileBackendError, PollEvents, Stat, TruncateLength, VFile, VFileFlags, VFileType, + DefaultFileBackendError, PollEvents, Stat, TruncateLength, VFile, VFileFlags, Vnode, }; use crate::process::{FileDesc, VThread}; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; @@ -34,9 +34,7 @@ impl KernelQueueManager { filedesc.insert_kqueue(kq.clone()); Ok(VFile::new( - VFileType::KernelQueue, VFileFlags::READ | VFileFlags::WRITE, - None, Box::new(FileBackend(kq)), )) }, @@ -90,4 +88,8 @@ impl crate::fs::FileBackend for FileBackend { ) -> Result<(), Box> { Err(Box::new(DefaultFileBackendError::InvalidValue)) } + + fn vnode(&self) -> Option<&Arc> { + None + } } diff --git a/src/kernel/src/net/mod.rs b/src/kernel/src/net/mod.rs index f45d42402..4131c6c50 100644 --- a/src/kernel/src/net/mod.rs +++ b/src/kernel/src/net/mod.rs @@ -1,12 +1,10 @@ +use self::socket::{Socket, SocketCreateError, SocketFileBackend}; use crate::budget::BudgetType; -use crate::errno::{Errno, EFAULT, EINVAL, ENAMETOOLONG}; -use crate::fs::{IoVec, VFile, VFileFlags, VFileType}; -use crate::process::GetSocketError; -use crate::{arnd, info}; -use crate::{ - process::VThread, - syscalls::{SysErr, SysIn, SysOut, Syscalls}, -}; +use crate::errno::{Errno, EFAULT, EINVAL, ENAMETOOLONG, ENOTSOCK}; +use crate::fs::{IoVec, VFile, VFileFlags}; +use crate::info; +use crate::process::VThread; +use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; use bitflags::bitflags; use macros::Errno; use std::fmt::Debug; @@ -14,11 +12,10 @@ use std::num::NonZeroI32; use std::sync::Arc; use thiserror::Error; -pub use self::socket::*; - mod proto; mod socket; +/// Provides networking services (e.g. socket). pub struct NetManager {} impl NetManager { @@ -43,7 +40,6 @@ impl NetManager { net } - #[allow(unused_variables)] // TODO: Remove this when implementing fn sys_recvmsg(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let msg: *mut MsgHdr = i.args[1].into(); @@ -102,7 +98,6 @@ impl NetManager { let fd: i32 = i.args[0].try_into().unwrap(); let ptr: *const u8 = i.args[1].into(); let len: i32 = i.args[2].try_into().unwrap(); - let addr = unsafe { SockAddr::get(ptr, len) }?; info!("Binding socket at fd {fd} to {addr:?}."); @@ -112,10 +107,15 @@ impl NetManager { Ok(SysOut::ZERO) } - fn bind(&self, fd: i32, addr: &SockAddr, td: &VThread) -> Result<(), BindError> { - let socket = td.proc().files().get_socket(fd)?; + /// See `kern_bind` on the PS4 for a reference. + fn bind(&self, fd: i32, addr: &SockAddr, td: &VThread) -> Result<(), SysErr> { + let file = td.proc().files().get(fd)?; + let sock = file + .backend::() + .ok_or(SysErr::Raw(ENOTSOCK))? + .as_sock(); - socket.bind(addr, td)?; + sock.bind(addr, td)?; Ok(()) } @@ -153,7 +153,7 @@ impl NetManager { match buf.as_mut() { Some(buf) => match op { // bnet_get_secure_seed - 0x14 if buflen > 3 => arnd::rand_bytes(&mut buf[..4]), + 0x14 if buflen > 3 => crate::arnd::rand_bytes(&mut buf[..4]), _ => todo!("netcontrol with op = {op}"), }, None => todo!("netcontrol with buf = null"), @@ -187,8 +187,11 @@ impl NetManager { fn sys_listen(self: &Arc, td: &VThread, i: &SysIn) -> Result { let fd: i32 = i.args[0].try_into().unwrap(); let backlog: i32 = i.args[1].try_into().unwrap(); - - let socket = td.proc().files().get_socket(fd)?; + let file = td.proc().files().get(fd)?; + let socket = file + .backend::() + .ok_or(SysErr::Raw(ENOTSOCK))? + .as_sock(); socket.listen(backlog, Some(td))?; @@ -210,17 +213,9 @@ impl NetManager { |_| { let so = Socket::new(domain, ty, proto, td.cred(), td, None)?; - let ty = if domain == 1 { - VFileType::IpcSocket - } else { - VFileType::Socket - }; - Ok(VFile::new( - ty, VFileFlags::READ | VFileFlags::WRITE, - None, - todo!(), + SocketFileBackend::new(so), )) }, budget, @@ -246,7 +241,7 @@ impl NetManager { } #[allow(unused_variables)] // TODO: Remove this when implementing - fn connect(&self, fd: i32, addr: &SockAddr, td: &VThread) -> Result<(), ConnectError> { + fn connect(&self, fd: i32, addr: &SockAddr, td: &VThread) -> Result<(), SysErr> { todo!("connect") } @@ -278,17 +273,9 @@ impl NetManager { |_| { let so = Socket::new(domain, ty, proto, td.cred(), td, name)?; - let ty = if domain == 1 { - VFileType::IpcSocket - } else { - VFileType::Socket - }; - Ok(VFile::new( - ty, VFileFlags::READ | VFileFlags::WRITE, - None, - todo!(), + SocketFileBackend::new(so), )) }, budget, @@ -417,7 +404,6 @@ struct MsgHdr<'a> { pub struct SockAddr([u8]); impl SockAddr { - #[allow(unused_variables)] // TODO: Remove this when implementing pub unsafe fn get(ptr: *const u8, len: i32) -> Result, GetSockAddrError> { if len > 255 { return Err(GetSockAddrError::TooLong); @@ -454,24 +440,6 @@ impl std::fmt::Debug for SockAddr { enum SockOpt {} -#[derive(Debug, Error, Errno)] -enum ConnectError { - #[error("failed to get socket")] - GetSocketError(#[from] GetSocketError), - - #[error("failed to connect")] - ConnectError(#[from] Box), -} - -#[derive(Debug, Error, Errno)] -enum BindError { - #[error("failed to get socket")] - GetSocketError(#[from] GetSocketError), - - #[error("failed to bind")] - BindError(#[from] Box), -} - #[derive(Debug, Error, Errno)] enum SetOptError { #[error("invalid value or length")] diff --git a/src/kernel/src/net/socket.rs b/src/kernel/src/net/socket.rs index 0a98b81c1..cad64d8db 100644 --- a/src/kernel/src/net/socket.rs +++ b/src/kernel/src/net/socket.rs @@ -3,7 +3,7 @@ use super::{GetOptError, SetOptError, SockAddr, SockOpt}; use crate::errno::{Errno, EPROTONOSUPPORT}; use crate::fs::{ DefaultFileBackendError, FileBackend, IoCmd, IoLen, IoVec, IoVecMut, PollEvents, Stat, - TruncateLength, VFile, + TruncateLength, VFile, Vnode, }; use crate::process::VThread; use crate::ucred::Ucred; @@ -94,7 +94,21 @@ impl Socket { } } -impl FileBackend for Socket { +/// Implementation of [`FileBackend`] for [`Socket`]. +#[derive(Debug)] +pub struct SocketFileBackend(Arc); + +impl SocketFileBackend { + pub fn new(sock: Arc) -> Box { + Box::new(Self(sock)) + } + + pub fn as_sock(&self) -> &Arc { + &self.0 + } +} + +impl FileBackend for SocketFileBackend { fn is_seekable(&self) -> bool { todo!() } @@ -136,7 +150,7 @@ impl FileBackend for Socket { IoCmd::SIOCSPGRP(_) => todo!("socket ioctl with SIOCSPGRP"), IoCmd::SIOCGPGRP(_) => todo!("socket ioctl with SIOCGPGRP"), IoCmd::SIOCATMARK(_) => todo!("socket ioctl with SIOCATMARK"), - _ => self.backend.control(todo!(), cmd, td), + _ => self.0.backend.control(todo!(), cmd, td), } } @@ -158,6 +172,10 @@ impl FileBackend for Socket { ) -> Result<(), Box> { Err(Box::new(DefaultFileBackendError::InvalidValue)) } + + fn vnode(&self) -> Option<&Arc> { + None + } } #[derive(Debug, Error, Errno)] diff --git a/src/kernel/src/process/filedesc.rs b/src/kernel/src/process/filedesc.rs index 9a3e03098..ee002fbec 100644 --- a/src/kernel/src/process/filedesc.rs +++ b/src/kernel/src/process/filedesc.rs @@ -1,8 +1,7 @@ use crate::budget::BudgetType; -use crate::errno::{Errno, EBADF, ENOTSOCK}; -use crate::fs::{VFile, VFileFlags, VFileType, Vnode}; +use crate::errno::{Errno, EBADF}; +use crate::fs::{VFile, VFileFlags, Vnode}; use crate::kqueue::KernelQueue; -use crate::net::Socket; use gmtx::{Gutex, GutexGroup}; use macros::Errno; use std::collections::VecDeque; @@ -113,19 +112,6 @@ impl FileDesc { panic!("Too many files has been opened."); } - // TODO: (maybe) implement capabilities - - /// See `getsock_cap` on the PS4 for a reference. - pub fn get_socket(&self, fd: i32) -> Result, GetSocketError> { - let file = self.get(fd)?; - - let (VFileType::Socket | VFileType::IpcSocket) = file.ty() else { - return Err(GetSocketError::NotSocket); - }; - - Ok(todo!()) - } - /// See `fget` on the PS4 for a reference. pub fn get(&self, fd: i32) -> Result, GetFileError> { self.get_internal(fd, VFileFlags::empty()) @@ -181,16 +167,6 @@ impl FileDesc { } } -#[derive(Debug, Error, Errno)] -pub enum GetSocketError { - #[error("failed to get file")] - GetFileError(#[from] GetFileError), - - #[error("file is not a socket")] - #[errno(ENOTSOCK)] - NotSocket, -} - #[derive(Debug, Error, Errno)] pub enum GetFileError { #[error("got negative file descriptor")] diff --git a/src/kernel/src/shm/mod.rs b/src/kernel/src/shm/mod.rs index 7774a611f..15a68e649 100644 --- a/src/kernel/src/shm/mod.rs +++ b/src/kernel/src/shm/mod.rs @@ -2,6 +2,7 @@ use crate::errno::{Errno, EINVAL}; use crate::fs::{ check_access, Access, AccessError, DefaultFileBackendError, FileBackend, IoCmd, IoLen, IoVec, IoVecMut, Mode, OpenFlags, PollEvents, Stat, TruncateLength, VFile, VFileFlags, VPathBuf, + Vnode, }; use crate::process::VThread; use crate::syscalls::{SysErr, SysIn, SysOut, Syscalls}; @@ -67,7 +68,7 @@ pub enum ShmPath { /// An implementation of the `shmfd` structure. #[derive(Debug)] #[allow(unused_variables)] // TODO: remove when used. -pub struct SharedMemory { +struct SharedMemory { uid: Uid, gid: Gid, mode: Mode, @@ -153,6 +154,10 @@ impl FileBackend for SharedMemory { Ok(()) } + + fn vnode(&self) -> Option<&Arc> { + todo!() + } } #[derive(Debug, Error, Errno)]