Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device trait #657

Merged
merged 4 commits into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 90 additions & 1 deletion src/kernel/src/fs/dev/cdev.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
use super::dirent::Dirent;
use crate::errno::Errno;
use crate::fs::{Mode, OpenFlags, VFile};
use crate::errno::ENODEV;
use crate::fs::Uio;
use crate::fs::{FileBackend, IoCmd, Mode, OpenFlags, Stat, TruncateLength, UioMut, VFile};
use crate::process::VThread;
use crate::time::TimeSpec;
use crate::ucred::{Gid, Ucred, Uid};
use bitflags::bitflags;
use gmtx::{Gutex, GutexGroup, GutexReadGuard, GutexWriteGuard};
use macros::Errno;
use std::fmt::Debug;
use std::sync::{Arc, Weak};
use thiserror::Error;

/// An implementation of `cdev` and `cdev_priv` structures.
#[derive(Debug)]
Expand Down Expand Up @@ -98,6 +103,53 @@ impl Cdev {
}
}

impl FileBackend for Cdev {
#[allow(unused_variables)] // TODO: remove when implementing
fn read(
self: &Arc<Self>,
file: &VFile,
buf: &mut UioMut,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}

#[allow(unused_variables)] // TODO: remove when implementing
fn write(
self: &Arc<Self>,
file: &VFile,
buf: &mut Uio,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}

#[allow(unused_variables)] // TODO: remove when implementing
fn ioctl(
self: &Arc<Self>,
file: &VFile,
cmd: IoCmd,
td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
todo!()
}

#[allow(unused_variables)] // TODO: remove when implementing
fn stat(self: &Arc<Self>, file: &VFile, td: Option<&VThread>) -> Result<Stat, Box<dyn Errno>> {
todo!()
}

#[allow(unused_variables)] // TODO: remove when implementing
fn truncate(
self: &Arc<Self>,
file: &VFile,
length: TruncateLength,
td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
todo!()
}
}

bitflags! {
/// Flags for [`Cdev`].
#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -149,3 +201,40 @@ bitflags! {
pub type CdevOpen = fn(&Arc<Cdev>, OpenFlags, i32, Option<&VThread>) -> Result<(), Box<dyn Errno>>;
pub type CdevFd =
fn(&Arc<Cdev>, OpenFlags, Option<&VThread>, Option<&mut VFile>) -> Result<(), Box<dyn Errno>>;

/// An implementation of the `cdevsw` structure.
pub(super) trait Device: Debug + Sync + Send + 'static {
SuchAFuriousDeath marked this conversation as resolved.
Show resolved Hide resolved
#[allow(unused_variables)]
fn read(
self: Arc<Self>,
data: &mut [u8],
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
Err(Box::new(DefaultError::ReadNotSupported))
}

#[allow(unused_variables)]
fn write(self: Arc<Self>, data: &[u8], td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
Err(Box::new(DefaultError::WriteNotSupported))
}

#[allow(unused_variables)]
fn ioctl(self: Arc<Self>, cmd: IoCmd, td: Option<&VThread>) -> Result<(), Box<dyn Errno>> {
Err(Box::new(DefaultError::IoctlNotSupported))
}
}

#[derive(Debug, Error, Errno)]
pub(super) enum DefaultError {
#[error("read not supported")]
#[errno(ENODEV)]
ReadNotSupported,

#[error("write not supported")]
#[errno(ENODEV)]
WriteNotSupported,

#[error("ioctl not supported")]
#[errno(ENODEV)]
IoctlNotSupported,
}
28 changes: 17 additions & 11 deletions src/kernel/src/fs/file.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{IoCmd, Offset, Stat, TruncateLength, Uio, UioMut, Vnode};
use super::{Cdev, IoCmd, Offset, Stat, TruncateLength, Uio, UioMut, Vnode};
use crate::dmem::BlockPool;
use crate::errno::Errno;
use crate::errno::{EINVAL, ENOTTY, ENXIO, EOPNOTSUPP};
Expand All @@ -16,14 +16,14 @@ use thiserror::Error;
/// An implementation of `file` structure.
#[derive(Debug)]
pub struct VFile {
backend: VFileType, // f_type
flags: VFileFlags, // f_flag
ty: VFileType, // f_type
flags: VFileFlags, // f_flag
}

impl VFile {
pub(super) fn new(backend: VFileType) -> Self {
pub(super) fn new(ty: VFileType) -> Self {
Self {
backend,
ty,
flags: VFileFlags::empty(),
}
}
Expand Down Expand Up @@ -82,42 +82,46 @@ impl VFile {
}

fn read(&self, buf: &mut UioMut, td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
match &self.backend {
match &self.ty {
VFileType::Vnode(vn) => vn.read(self, buf, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.read(self, buf, td),
VFileType::KernelQueue(kq) => kq.read(self, buf, td),
VFileType::SharedMemory(shm) => shm.read(self, buf, td),
VFileType::Device(dev) => dev.read(self, buf, td),
VFileType::Blockpool(bp) => bp.read(self, buf, td),
}
}

fn write(&self, buf: &mut Uio, td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
match &self.backend {
match &self.ty {
VFileType::Vnode(vn) => vn.write(self, buf, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.write(self, buf, td),
VFileType::KernelQueue(kq) => kq.write(self, buf, td),
VFileType::SharedMemory(shm) => shm.write(self, buf, td),
VFileType::Device(dev) => dev.write(self, buf, td),
VFileType::Blockpool(bp) => bp.write(self, buf, td),
}
}

/// See `fo_ioctl` on the PS4 for a reference.
pub fn ioctl(&self, cmd: IoCmd, td: Option<&VThread>) -> Result<(), Box<dyn Errno>> {
match &self.backend {
match &self.ty {
VFileType::Vnode(vn) => vn.ioctl(self, cmd, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.ioctl(self, cmd, td),
VFileType::KernelQueue(kq) => kq.ioctl(self, cmd, td),
VFileType::SharedMemory(shm) => shm.ioctl(self, cmd, td),
VFileType::Device(dev) => dev.ioctl(self, cmd, td),
VFileType::Blockpool(bp) => bp.ioctl(self, cmd, td),
}
}

pub fn stat(&self, td: Option<&VThread>) -> Result<Stat, Box<dyn Errno>> {
match &self.backend {
match &self.ty {
VFileType::Vnode(vn) => vn.stat(self, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.stat(self, td),
VFileType::KernelQueue(kq) => kq.stat(self, td),
VFileType::SharedMemory(shm) => shm.stat(self, td),
VFileType::Device(dev) => dev.stat(self, td),
VFileType::Blockpool(bp) => bp.stat(self, td),
}
}
Expand All @@ -127,17 +131,18 @@ impl VFile {
length: TruncateLength,
td: Option<&VThread>,
) -> Result<(), Box<dyn Errno>> {
match &self.backend {
match &self.ty {
VFileType::Vnode(vn) => vn.truncate(self, length, td),
VFileType::Socket(so) | VFileType::IpcSocket(so) => so.truncate(self, length, td),
VFileType::KernelQueue(kq) => kq.truncate(self, length, td),
VFileType::SharedMemory(shm) => shm.truncate(self, length, td),
VFileType::Device(dev) => dev.truncate(self, length, td),
VFileType::Blockpool(bp) => bp.truncate(self, length, td),
}
}

pub fn is_seekable(&self) -> bool {
matches!(self.backend, VFileType::Vnode(_))
matches!(self.ty, VFileType::Vnode(_) | VFileType::Device(_))
}
}

Expand Down Expand Up @@ -170,6 +175,7 @@ pub enum VFileType {
Socket(Arc<Socket>), // DTYPE_SOCKET = 2,
KernelQueue(Arc<KernelQueue>), // DTYPE_KQUEUE = 5,
SharedMemory(Arc<Shm>), // DTYPE_SHM = 8,
Device(Arc<Cdev>), // DTYPE_DEV = 11,
IpcSocket(Arc<Socket>), // DTYPE_IPCSOCKET = 15,
Blockpool(Arc<BlockPool>), // DTYPE_BLOCKPOOL = 17,
}
Expand Down
4 changes: 2 additions & 2 deletions src/kernel/src/fs/vnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Vnode {
fs: &Arc<Mount>,
ty: VnodeType,
tag: &'static str,
backend: impl VnodeBackend + 'static,
backend: impl VnodeBackend,
) -> Arc<Self> {
let gg = GutexGroup::new();

Expand Down Expand Up @@ -191,7 +191,7 @@ pub enum VnodeType {
/// `vop_bypass` because it required the return type for all operations to be the same.
///
/// All default implementation here are the implementation of `default_vnodeops`.
pub(super) trait VnodeBackend: Debug + Send + Sync {
pub(super) trait VnodeBackend: Debug + Send + Sync + 'static {
/// An implementation of `vop_access`.
fn access(
self: Arc<Self>,
Expand Down