Removes VFileType (#853)

This commit is contained in:
Putta Khunchalee 2024-04-21 19:09:37 +07:00 committed by GitHub
parent 54b851c5a7
commit 3c9cfd5787
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 125 additions and 142 deletions

View file

@ -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
}

View file

@ -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<Vnode>> {
None
}
}
#[repr(C)]

View file

@ -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}");

View file

@ -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<CharacterDevice>);
pub(super) struct CdevFileBackend {
vnode: Arc<Vnode>,
dev: Arc<CharacterDevice>,
}
impl CdevFileBackend {
pub fn new(dev: Arc<CharacterDevice>) -> Self {
Self(dev)
pub fn new(vnode: Arc<Vnode>, dev: Arc<CharacterDevice>) -> 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<dyn Errno>> {
todo!()
}
fn vnode(&self) -> Option<&Arc<Vnode>> {
Some(&self.vnode)
}
}
bitflags! {

View file

@ -196,7 +196,7 @@ impl crate::fs::VnodeBackend for VnodeBackend {
fn to_file_backend(&self, vn: &Arc<Vnode>) -> Box<dyn FileBackend> {
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())),
}
}

View file

@ -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<Arc<Vnode>>, // f_vnode
offset: Gutex<u64>, // f_offset
flags: VFileFlags, // f_flag
offset: Gutex<u64>, // f_offset
backend: Box<dyn FileBackend>,
}
impl VFile {
pub fn new(
ty: VFileType,
flags: VFileFlags,
vnode: Option<Arc<Vnode>>,
backend: Box<dyn FileBackend>,
) -> Self {
pub fn new(flags: VFileFlags, backend: Box<dyn FileBackend>) -> 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<Vnode>> {
self.vnode.as_ref()
self.backend.vnode()
}
pub fn ioctl(&self, cmd: IoCmd, td: Option<&VThread>) -> Result<(), Box<dyn Errno>> {
@ -69,6 +57,25 @@ impl VFile {
) -> Result<(), Box<dyn Errno>> {
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<T: FileBackend>(&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::<T>() {
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<dyn Errno>> {
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<Vnode>>;
}
#[derive(Debug, Error, Errno)]

View file

@ -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(

View file

@ -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<dyn Errno>> {
todo!()
}
fn vnode(&self) -> Option<&Arc<Vnode>> {
Some(&self.0)
}
}
/// Represents an error when default implementation of [`VnodeBackend`] fails.

View file

@ -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<dyn Errno>> {
Err(Box::new(DefaultFileBackendError::InvalidValue))
}
fn vnode(&self) -> Option<&Arc<Vnode>> {
None
}
}

View file

@ -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<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
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::<SocketFileBackend>()
.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<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
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::<SocketFileBackend>()
.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<Box<Self>, 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<dyn Errno>),
}
#[derive(Debug, Error, Errno)]
enum BindError {
#[error("failed to get socket")]
GetSocketError(#[from] GetSocketError),
#[error("failed to bind")]
BindError(#[from] Box<dyn Errno>),
}
#[derive(Debug, Error, Errno)]
enum SetOptError {
#[error("invalid value or length")]

View file

@ -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<Socket>);
impl SocketFileBackend {
pub fn new(sock: Arc<Socket>) -> Box<Self> {
Box::new(Self(sock))
}
pub fn as_sock(&self) -> &Arc<Socket> {
&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<dyn Errno>> {
Err(Box::new(DefaultFileBackendError::InvalidValue))
}
fn vnode(&self) -> Option<&Arc<Vnode>> {
None
}
}
#[derive(Debug, Error, Errno)]

View file

@ -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<Arc<Socket>, 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<Arc<VFile>, 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")]

View file

@ -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<Vnode>> {
todo!()
}
}
#[derive(Debug, Error, Errno)]