Add trait FileIo and refactor current devices

This commit is contained in:
Jianfeng Jiang 2023-11-16 17:26:42 +08:00 committed by Tate, Hongliang Tian
parent 43fd1a52fa
commit 001326110e
15 changed files with 147 additions and 153 deletions

View File

@ -12,6 +12,8 @@ pub use pty::{PtyMaster, PtySlave};
pub use random::Random; pub use random::Random;
pub use urandom::Urandom; pub use urandom::Urandom;
use self::tty::get_n_tty;
/// Init the device node in fs, must be called after mounting rootfs. /// Init the device node in fs, must be called after mounting rootfs.
pub fn init() -> Result<()> { pub fn init() -> Result<()> {
let null = Arc::new(null::Null); let null = Arc::new(null::Null);
@ -19,7 +21,9 @@ pub fn init() -> Result<()> {
let zero = Arc::new(zero::Zero); let zero = Arc::new(zero::Zero);
add_node(zero, "zero")?; add_node(zero, "zero")?;
tty::init(); tty::init();
let tty = tty::get_n_tty().clone(); let console = get_n_tty().clone();
add_node(console, "console")?;
let tty = Arc::new(tty::TtyDevice);
add_node(tty, "tty")?; add_node(tty, "tty")?;
let random = Arc::new(random::Random); let random = Arc::new(random::Random);
add_node(random, "random")?; add_node(random, "random")?;

View File

@ -1,5 +1,8 @@
use super::*; use super::*;
use crate::events::IoEvents;
use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
pub struct Null; pub struct Null;
@ -12,7 +15,9 @@ impl Device for Null {
// Same value with Linux // Same value with Linux
DeviceId::new(1, 3) DeviceId::new(1, 3)
} }
}
impl FileIo for Null {
fn read(&self, _buf: &mut [u8]) -> Result<usize> { fn read(&self, _buf: &mut [u8]) -> Result<usize> {
Ok(0) Ok(0)
} }
@ -20,4 +25,9 @@ impl Device for Null {
fn write(&self, buf: &[u8]) -> Result<usize> { fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let events = IoEvents::IN | IoEvents::OUT;
events & mask
}
} }

View File

@ -1,5 +1,8 @@
use crate::events::IoEvents;
use crate::fs::device::{Device, DeviceId, DeviceType}; use crate::fs::device::{Device, DeviceId, DeviceType};
use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
pub struct Random; pub struct Random;
@ -19,7 +22,9 @@ impl Device for Random {
// The same value as Linux // The same value as Linux
DeviceId::new(1, 8) DeviceId::new(1, 8)
} }
}
impl FileIo for Random {
fn read(&self, buf: &mut [u8]) -> Result<usize> { fn read(&self, buf: &mut [u8]) -> Result<usize> {
Self::getrandom(buf) Self::getrandom(buf)
} }
@ -27,6 +32,11 @@ impl Device for Random {
fn write(&self, buf: &[u8]) -> Result<usize> { fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let events = IoEvents::IN | IoEvents::OUT;
events & mask
}
} }
impl From<getrandom::Error> for Error { impl From<getrandom::Error> for Error {

View File

@ -1,5 +1,8 @@
use crate::events::IoEvents;
use crate::fs::device::{Device, DeviceId, DeviceType}; use crate::fs::device::{Device, DeviceId, DeviceType};
use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
pub struct Urandom; pub struct Urandom;
@ -19,7 +22,9 @@ impl Device for Urandom {
// The same value as Linux // The same value as Linux
DeviceId::new(1, 9) DeviceId::new(1, 9)
} }
}
impl FileIo for Urandom {
fn read(&self, buf: &mut [u8]) -> Result<usize> { fn read(&self, buf: &mut [u8]) -> Result<usize> {
Self::getrandom(buf) Self::getrandom(buf)
} }
@ -27,4 +32,9 @@ impl Device for Urandom {
fn write(&self, buf: &[u8]) -> Result<usize> { fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let events = IoEvents::IN | IoEvents::OUT;
events & mask
}
} }

View File

@ -1,5 +1,8 @@
use super::*; use super::*;
use crate::events::IoEvents;
use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
pub struct Zero; pub struct Zero;
@ -12,7 +15,9 @@ impl Device for Zero {
// Same value with Linux // Same value with Linux
DeviceId::new(1, 5) DeviceId::new(1, 5)
} }
}
impl FileIo for Zero {
fn read(&self, buf: &mut [u8]) -> Result<usize> { fn read(&self, buf: &mut [u8]) -> Result<usize> {
for byte in buf.iter_mut() { for byte in buf.iter_mut() {
*byte = 0; *byte = 0;
@ -23,4 +28,9 @@ impl Device for Zero {
fn write(&self, buf: &[u8]) -> Result<usize> { fn write(&self, buf: &[u8]) -> Result<usize> {
Ok(buf.len()) Ok(buf.len())
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let events = IoEvents::IN | IoEvents::OUT;
events & mask
}
} }

View File

@ -1,33 +1,21 @@
use crate::events::IoEvents;
use crate::fs::fs_resolver::{FsPath, FsResolver}; use crate::fs::fs_resolver::{FsPath, FsResolver};
use crate::fs::utils::Dentry; use crate::fs::utils::Dentry;
use crate::fs::utils::{InodeMode, InodeType, IoctlCmd}; use crate::fs::utils::{InodeMode, InodeType};
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
use super::inode_handle::FileIo;
/// The abstract of device /// The abstract of device
pub trait Device: Sync + Send { pub trait Device: Sync + Send + FileIo {
/// Return the device type. /// Return the device type.
fn type_(&self) -> DeviceType; fn type_(&self) -> DeviceType;
/// Return the device ID. /// Return the device ID.
fn id(&self) -> DeviceId; fn id(&self) -> DeviceId;
/// Read from the device. /// Open a device.
fn read(&self, buf: &mut [u8]) -> Result<usize>; fn open(&self) -> Result<Option<Arc<dyn FileIo>>> {
Ok(None)
/// Write to the device.
fn write(&self, buf: &[u8]) -> Result<usize>;
/// Poll on the device.
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
let events = IoEvents::IN | IoEvents::OUT;
events & mask
}
/// Ioctl on the device.
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
} }
} }

View File

@ -1,106 +0,0 @@
use crate::events::IoEvents;
use crate::fs::file_handle::FileLike;
use crate::prelude::*;
use crate::process::signal::Poller;
use super::*;
use crate::device::PtyMaster;
/// Pty master inode for the master device.
pub struct PtyMasterInode(Arc<PtyMaster>);
impl PtyMasterInode {
pub fn new(device: Arc<PtyMaster>) -> Arc<Self> {
Arc::new(Self(device))
}
}
impl Drop for PtyMasterInode {
fn drop(&mut self) {
// Remove the slave from fs.
let fs = self.0.ptmx().fs();
let devpts = fs.downcast_ref::<DevPts>().unwrap();
let index = self.0.index();
devpts.remove_slave(index);
}
}
impl Inode for PtyMasterInode {
/// Do not cache dentry in DCACHE.
///
/// Each file descriptor obtained by opening "/dev/ptmx" is an independent pty master
/// with its own associated pty slave.
fn is_dentry_cacheable(&self) -> bool {
false
}
fn len(&self) -> usize {
self.0.ptmx().metadata().size
}
fn resize(&self, new_size: usize) {}
fn metadata(&self) -> Metadata {
self.0.ptmx().metadata()
}
fn type_(&self) -> InodeType {
self.0.ptmx().metadata().type_
}
fn mode(&self) -> InodeMode {
self.0.ptmx().metadata().mode
}
fn set_mode(&self, mode: InodeMode) {}
fn atime(&self) -> Duration {
self.0.ptmx().metadata().atime
}
fn set_atime(&self, time: Duration) {}
fn mtime(&self) -> Duration {
self.0.ptmx().metadata().mtime
}
fn set_mtime(&self, time: Duration) {}
fn read_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
Ok(())
}
fn write_page(&self, idx: usize, frame: &VmFrame) -> Result<()> {
Ok(())
}
fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
self.0.read(buf)
}
fn read_direct_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
self.0.read(buf)
}
fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
self.0.write(buf)
}
fn write_direct_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
self.0.write(buf)
}
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
self.0.ioctl(cmd, arg)
}
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.0.poll(mask, poller)
}
fn fs(&self) -> Arc<dyn FileSystem> {
self.0.ptmx().fs()
}
}

View File

@ -1,3 +1,4 @@
use crate::device::PtyMaster;
use crate::fs::device::{Device, DeviceId, DeviceType}; use crate::fs::device::{Device, DeviceId, DeviceType};
use crate::fs::utils::{ use crate::fs::utils::{
DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata, DirentVisitor, FileSystem, FsFlags, Inode, InodeMode, InodeType, IoctlCmd, Metadata,
@ -9,11 +10,9 @@ use core::time::Duration;
use jinux_frame::vm::VmFrame; use jinux_frame::vm::VmFrame;
use jinux_util::{id_allocator::IdAlloc, slot_vec::SlotVec}; use jinux_util::{id_allocator::IdAlloc, slot_vec::SlotVec};
use self::master::PtyMasterInode;
use self::ptmx::Ptmx; use self::ptmx::Ptmx;
use self::slave::PtySlaveInode; use self::slave::PtySlaveInode;
mod master;
mod ptmx; mod ptmx;
mod slave; mod slave;
@ -52,7 +51,7 @@ impl DevPts {
} }
/// Create the master and slave pair. /// Create the master and slave pair.
fn create_master_slave_pair(&self) -> Result<(Arc<PtyMasterInode>, Arc<PtySlaveInode>)> { fn create_master_slave_pair(&self) -> Result<(Arc<PtyMaster>, Arc<PtySlaveInode>)> {
let index = self let index = self
.index_alloc .index_alloc
.lock() .lock()
@ -61,17 +60,16 @@ impl DevPts {
let (master, slave) = crate::device::new_pty_pair(index as u32, self.root.ptmx.clone())?; let (master, slave) = crate::device::new_pty_pair(index as u32, self.root.ptmx.clone())?;
let master_inode = PtyMasterInode::new(master);
let slave_inode = PtySlaveInode::new(slave, self.this.clone()); let slave_inode = PtySlaveInode::new(slave, self.this.clone());
self.root.add_slave(index.to_string(), slave_inode.clone()); self.root.add_slave(index.to_string(), slave_inode.clone());
Ok((master_inode, slave_inode)) Ok((master, slave_inode))
} }
/// Remove the slave from fs. /// Remove the slave from fs.
/// ///
/// This is called when the master is being dropped. /// This is called when the master is being dropped.
fn remove_slave(&self, index: u32) -> Option<Arc<PtySlaveInode>> { pub fn remove_slave(&self, index: u32) -> Option<Arc<PtySlaveInode>> {
let removed_slave = self.root.remove_slave(&index.to_string()); let removed_slave = self.root.remove_slave(&index.to_string());
if removed_slave.is_some() { if removed_slave.is_some() {
self.index_alloc.lock().free(index as usize); self.index_alloc.lock().free(index as usize);
@ -241,7 +239,7 @@ impl Inode for RootInode {
let inode = match name { let inode = match name {
"." | ".." => self.fs().root_inode(), "." | ".." => self.fs().root_inode(),
// Call the "open" method of ptmx to create a master and slave pair. // Call the "open" method of ptmx to create a master and slave pair.
"ptmx" => self.ptmx.open()?, "ptmx" => self.ptmx.clone(),
slave => self slave => self
.slaves .slaves
.read() .read()

View File

@ -1,4 +1,8 @@
use crate::device::PtyMaster;
use crate::events::IoEvents;
use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
use super::*; use super::*;
@ -14,12 +18,14 @@ const PTMX_MINOR_NUM: u32 = 2;
pub struct Ptmx { pub struct Ptmx {
inner: Inner, inner: Inner,
metadata: Metadata, metadata: Metadata,
fs: Weak<DevPts>,
} }
#[derive(Clone)]
struct Inner(Weak<DevPts>);
impl Ptmx { impl Ptmx {
pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> { pub fn new(sb: &SuperBlock, fs: Weak<DevPts>) -> Arc<Self> {
let inner = Inner; let inner = Inner(fs);
Arc::new(Self { Arc::new(Self {
metadata: Metadata::new_device( metadata: Metadata::new_device(
PTMX_INO, PTMX_INO,
@ -28,20 +34,19 @@ impl Ptmx {
&inner, &inner,
), ),
inner, inner,
fs,
}) })
} }
/// The open method for ptmx. /// The open method for ptmx.
/// ///
/// Creates a master and slave pair and returns the master inode. /// Creates a master and slave pair and returns the master inode.
pub fn open(&self) -> Result<Arc<PtyMasterInode>> { pub fn open(&self) -> Result<Arc<PtyMaster>> {
let (master, _) = self.devpts().create_master_slave_pair()?; let (master, _) = self.devpts().create_master_slave_pair()?;
Ok(master) Ok(master)
} }
pub fn devpts(&self) -> Arc<DevPts> { pub fn devpts(&self) -> Arc<DevPts> {
self.fs.upgrade().unwrap() self.inner.0.upgrade().unwrap()
} }
pub fn device_type(&self) -> DeviceType { pub fn device_type(&self) -> DeviceType {
@ -121,13 +126,10 @@ impl Inode for Ptmx {
} }
fn as_device(&self) -> Option<Arc<dyn Device>> { fn as_device(&self) -> Option<Arc<dyn Device>> {
Some(Arc::new(self.inner)) Some(Arc::new(self.inner.clone()))
} }
} }
#[derive(Clone, Copy)]
struct Inner;
impl Device for Inner { impl Device for Inner {
fn type_(&self) -> DeviceType { fn type_(&self) -> DeviceType {
DeviceType::CharDevice DeviceType::CharDevice
@ -137,13 +139,23 @@ impl Device for Inner {
DeviceId::new(PTMX_MAJOR_NUM, PTMX_MINOR_NUM) DeviceId::new(PTMX_MAJOR_NUM, PTMX_MINOR_NUM)
} }
fn open(&self) -> Result<Option<Arc<dyn FileIo>>> {
let devpts = self.0.upgrade().unwrap();
let (master, _) = devpts.create_master_slave_pair()?;
Ok(Some(master as _))
}
}
impl FileIo for Inner {
fn read(&self, buf: &mut [u8]) -> Result<usize> { fn read(&self, buf: &mut [u8]) -> Result<usize> {
// do nothing because it should not be used to read. unreachable!()
Ok(0)
} }
fn write(&self, buf: &[u8]) -> Result<usize> { fn write(&self, buf: &[u8]) -> Result<usize> {
// do nothing because it should not be used to write. unreachable!()
Ok(buf.len()) }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
unreachable!()
} }
} }

View File

@ -1,4 +1,5 @@
use crate::events::IoEvents; use crate::events::IoEvents;
use crate::fs::inode_handle::FileIo;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;

View File

@ -1,8 +1,8 @@
//! Opend File Handle //! Opend File Handle
use crate::events::Observer; use crate::events::{IoEvents, Observer};
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::fs::utils::{AccessMode, IoEvents, IoctlCmd, Metadata, Poller, SeekFrom, StatusFlags}; use crate::fs::utils::{AccessMode, IoctlCmd, Metadata, SeekFrom, StatusFlags};
use crate::net::socket::Socket; use crate::net::socket::Socket;
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller; use crate::process::signal::Poller;

View File

@ -27,7 +27,7 @@ impl FileTable {
pub fn new_with_stdio() -> Self { pub fn new_with_stdio() -> Self {
let mut table = SlotVec::new(); let mut table = SlotVec::new();
let fs_resolver = FsResolver::new(); let fs_resolver = FsResolver::new();
let tty_path = FsPath::new(AT_FDCWD, "/dev/tty").expect("cannot find tty"); let tty_path = FsPath::new(AT_FDCWD, "/dev/console").expect("cannot find tty");
let stdin = { let stdin = {
let flags = AccessMode::O_RDONLY as u32; let flags = AccessMode::O_RDONLY as u32;
let mode = InodeMode::S_IRUSR; let mode = InodeMode::S_IRUSR;

View File

@ -21,8 +21,16 @@ impl InodeHandle<Rights> {
if access_mode.is_writable() && inode.type_() == InodeType::Dir { if access_mode.is_writable() && inode.type_() == InodeType::Dir {
return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write"); return_errno_with_message!(Errno::EISDIR, "Directory cannot open to write");
} }
let file_io = if let Some(device) = inode.as_device() {
device.open()?
} else {
None
};
let inner = Arc::new(InodeHandle_ { let inner = Arc::new(InodeHandle_ {
dentry, dentry,
file_io,
offset: Mutex::new(0), offset: Mutex::new(0),
access_mode, access_mode,
status_flags: AtomicU32::new(status_flags.bits()), status_flags: AtomicU32::new(status_flags.bits()),
@ -42,6 +50,7 @@ impl InodeHandle<Rights> {
if !self.1.contains(Rights::READ) { if !self.1.contains(Rights::READ) {
return_errno_with_message!(Errno::EBADF, "File is not readable"); return_errno_with_message!(Errno::EBADF, "File is not readable");
} }
self.0.read_to_end(buf) self.0.read_to_end(buf)
} }
@ -75,11 +84,11 @@ impl FileLike for InodeHandle<Rights> {
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents { fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.dentry().inode().poll(mask, poller) self.0.poll(mask, poller)
} }
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> { fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
self.dentry().inode().ioctl(cmd, arg) self.0.ioctl(cmd, arg)
} }
fn metadata(&self) -> Metadata { fn metadata(&self) -> Metadata {
@ -109,6 +118,6 @@ impl FileLike for InodeHandle<Rights> {
} }
fn as_device(&self) -> Option<Arc<dyn Device>> { fn as_device(&self) -> Option<Arc<dyn Device>> {
self.dentry().vnode().as_device() self.dentry().inode().as_device()
} }
} }

View File

@ -5,12 +5,14 @@ mod static_cap;
use core::sync::atomic::{AtomicU32, Ordering}; use core::sync::atomic::{AtomicU32, Ordering};
use crate::events::IoEvents;
use crate::fs::device::Device; use crate::fs::device::Device;
use crate::fs::file_handle::FileLike; use crate::fs::file_handle::FileLike;
use crate::fs::utils::{ use crate::fs::utils::{
AccessMode, Dentry, DirentVisitor, InodeType, IoctlCmd, Metadata, SeekFrom, StatusFlags, AccessMode, Dentry, DirentVisitor, InodeType, IoctlCmd, Metadata, SeekFrom, StatusFlags,
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::process::signal::Poller;
use jinux_rights::Rights; use jinux_rights::Rights;
#[derive(Debug)] #[derive(Debug)]
@ -18,6 +20,10 @@ pub struct InodeHandle<R = Rights>(Arc<InodeHandle_>, R);
struct InodeHandle_ { struct InodeHandle_ {
dentry: Arc<Dentry>, dentry: Arc<Dentry>,
/// `file_io` is Similar to `file_private` field in `file` structure in linux. If
/// `file_io` is Some, typical file operations including `read`, `write`, `poll`,
/// `ioctl` will be provided by `file_io`, instead of `dentry`.
file_io: Option<Arc<dyn FileIo>>,
offset: Mutex<usize>, offset: Mutex<usize>,
access_mode: AccessMode, access_mode: AccessMode,
status_flags: AtomicU32, status_flags: AtomicU32,
@ -26,6 +32,11 @@ struct InodeHandle_ {
impl InodeHandle_ { impl InodeHandle_ {
pub fn read(&self, buf: &mut [u8]) -> Result<usize> { pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
let mut offset = self.offset.lock(); let mut offset = self.offset.lock();
if let Some(ref file_io) = self.file_io {
return file_io.read(buf);
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().read_direct_at(*offset, buf)? self.dentry.inode().read_direct_at(*offset, buf)?
} else { } else {
@ -38,6 +49,11 @@ impl InodeHandle_ {
pub fn write(&self, buf: &[u8]) -> Result<usize> { pub fn write(&self, buf: &[u8]) -> Result<usize> {
let mut offset = self.offset.lock(); let mut offset = self.offset.lock();
if let Some(ref file_io) = self.file_io {
return file_io.write(buf);
}
if self.status_flags().contains(StatusFlags::O_APPEND) { if self.status_flags().contains(StatusFlags::O_APPEND) {
*offset = self.dentry.inode_len(); *offset = self.dentry.inode_len();
} }
@ -52,6 +68,10 @@ impl InodeHandle_ {
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> { pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
if self.file_io.is_some() {
return_errno_with_message!(Errno::EINVAL, "file io does not support read to end");
}
let len = if self.status_flags().contains(StatusFlags::O_DIRECT) { let len = if self.status_flags().contains(StatusFlags::O_DIRECT) {
self.dentry.inode().read_direct_to_end(buf)? self.dentry.inode().read_direct_to_end(buf)?
} else { } else {
@ -118,6 +138,22 @@ impl InodeHandle_ {
*offset += read_cnt; *offset += read_cnt;
Ok(read_cnt) Ok(read_cnt)
} }
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
if let Some(ref file_io) = self.file_io {
return file_io.poll(mask, poller);
}
self.dentry.inode().poll(mask, poller)
}
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
if let Some(ref file_io) = self.file_io {
return file_io.ioctl(cmd, arg);
}
self.dentry.inode().ioctl(cmd, arg)
}
} }
impl Debug for InodeHandle_ { impl Debug for InodeHandle_ {
@ -137,3 +173,15 @@ impl<R> InodeHandle<R> {
&self.0.dentry &self.0.dentry
} }
} }
pub trait FileIo: Send + Sync + 'static {
fn read(&self, buf: &mut [u8]) -> Result<usize>;
fn write(&self, buf: &[u8]) -> Result<usize>;
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents;
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
return_errno_with_message!(Errno::EINVAL, "ioctl is not supported");
}
}

View File

@ -91,7 +91,7 @@ impl DirOps for RootDirOps {
SelfSymOps::new_inode(this_ptr.clone()) SelfSymOps::new_inode(this_ptr.clone())
} else if let Ok(pid) = name.parse::<Pid>() { } else if let Ok(pid) = name.parse::<Pid>() {
let process_ref = let process_ref =
process_table::pid_to_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?; process_table::get_process(&pid).ok_or_else(|| Error::new(Errno::ENOENT))?;
PidDirOps::new_inode(process_ref, this_ptr.clone()) PidDirOps::new_inode(process_ref, this_ptr.clone())
} else { } else {
return_errno!(Errno::ENOENT); return_errno!(Errno::ENOENT);