Skip to content

Commit

Permalink
Implements seek and read on vfile (obhq#781)
Browse files Browse the repository at this point in the history
  • Loading branch information
SuchAFuriousDeath committed Mar 31, 2024
1 parent c04768c commit 807686a
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 30 deletions.
21 changes: 19 additions & 2 deletions src/kernel/src/fs/dev/vnode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use super::dirent::Dirent;
use super::{AllocVnodeError, DevFs};
use crate::errno::{Errno, EIO, ENOENT, ENOTDIR, ENXIO};
use crate::fs::{
check_access, Access, IoCmd, OpenFlags, RevokeFlags, VFileType, Vnode, VnodeAttrs, VnodeItem,
VnodeType,
check_access, Access, IoCmd, RevokeFlags, Uio, UioMut, Vnode, VnodeAttrs, VnodeType,
};
use crate::process::VThread;
use macros::Errno;
Expand Down Expand Up @@ -167,6 +166,24 @@ impl crate::fs::VnodeBackend for VnodeBackend {
// TODO: Implement this.
todo!()
}

fn read(
&self,
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut UioMut,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}

fn write(
&self,
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut Uio,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}
}

/// Represents an error when [`lookup()`] is failed.
Expand Down
39 changes: 34 additions & 5 deletions src/kernel/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{CharacterDevice, IoCmd, Offset, Stat, TruncateLength, Uio, UioMut, V
use crate::dmem::BlockPool;
use crate::errno::Errno;
use crate::errno::{EINVAL, ENOTTY, ENXIO, EOPNOTSUPP};
use crate::fs::PollEvents;
use crate::fs::{IoVec, PollEvents};
use crate::kqueue::KernelQueue;
use crate::net::Socket;
use crate::process::VThread;
Expand All @@ -19,13 +19,15 @@ use thiserror::Error;
pub struct VFile {
ty: VFileType, // f_type
flags: VFileFlags, // f_flag
offset: i64, // f_offset
}

impl VFile {
pub(super) fn new(ty: VFileType) -> Self {
Self {
ty,
flags: VFileFlags::empty(),
offset: 0,
}
}

Expand Down Expand Up @@ -90,7 +92,7 @@ impl VFile {

fn read(&self, buf: &mut UioMut, td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
match &self.ty {
VFileType::Vnode(vn) => vn.read(self, buf, td),
VFileType::Vnode(vn) => FileBackend::read(vn, 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),
Expand All @@ -101,7 +103,7 @@ impl VFile {

fn write(&self, buf: &mut Uio, td: Option<&VThread>) -> Result<usize, Box<dyn Errno>> {
match &self.ty {
VFileType::Vnode(vn) => vn.write(self, buf, td),
VFileType::Vnode(vn) => FileBackend::write(vn, 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),
Expand Down Expand Up @@ -154,12 +156,39 @@ impl Seek for VFile {
fn seek(&mut self, _pos: SeekFrom) -> std::io::Result<u64> {
todo!()
}

fn rewind(&mut self) -> std::io::Result<()> {
self.offset = 0;

Ok(())
}

fn stream_position(&mut self) -> std::io::Result<u64> {
if let Ok(offset) = self.offset.try_into() {
Ok(offset)
} else {
todo!()
}
}
}

impl Read for VFile {
#[allow(unused_variables)] // TODO: Remove when implementing.
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
todo!()
let ref mut iovec = IoVec::from_slice(buf);

let mut uio = UioMut::from_single_vec(iovec);

let Ok(read) = VFile::read(self, &mut uio, None) else {
todo!()
};

if let Ok(read) = TryInto::<i64>::try_into(read) {
self.offset += read;
} else {
todo!()
}

Ok(read)
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/kernel/src/fs/host/file.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::fs::UioMut;
use std::collections::HashMap;
use std::io::Error;
use std::mem::zeroed;
Expand Down Expand Up @@ -272,6 +273,16 @@ impl HostFile {
}
}

#[cfg(unix)]
pub(super) fn read(&self, buf: &mut UioMut) -> Result<usize, Error> {
todo!()
}

#[cfg(windows)]
pub(super) fn read(&self, buf: &mut UioMut) -> Result<usize, Error> {
todo!()
}

#[cfg(unix)]
fn stat(&self) -> Result<libc::stat, Error> {
use libc::fstat;
Expand Down
29 changes: 28 additions & 1 deletion src/kernel/src/fs/host/vnode.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::file::HostFile;
use super::{GetVnodeError, HostFs};
use crate::errno::{Errno, EEXIST, EIO, ENOENT, ENOTDIR};
use crate::fs::{Access, IoCmd, Mode, OpenFlags, VFileType, Vnode, VnodeAttrs, VnodeType};
use crate::fs::{Access, IoCmd, Mode, Uio, UioMut, Vnode, VnodeAttrs, VnodeType};
use crate::process::VThread;
use crate::ucred::{Gid, Uid};
use macros::Errno;
Expand Down Expand Up @@ -123,6 +123,26 @@ impl crate::fs::VnodeBackend for VnodeBackend {

Ok(vn)
}

fn read(
&self,
_: &Arc<Vnode>,
buf: &mut UioMut,
_: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
let read = self.file.read(buf).map_err(ReadError::ReadFailed)?;

Ok(read)
}

fn write(
&self,
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut Uio,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}
}

/// Represents an error when [`getattr()`] fails.
Expand Down Expand Up @@ -182,3 +202,10 @@ impl From<std::io::Error> for MkDirError {
}
}
}

#[derive(Debug, Error, Errno)]
enum ReadError {
#[error("read failed")]
#[errno(EIO)]
ReadFailed(#[source] std::io::Error),
}
2 changes: 1 addition & 1 deletion src/kernel/src/fs/mount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::collections::HashMap;
use std::convert::Infallible;
use std::fmt::Formatter;
use std::fmt::{Debug, Display, Error};
use std::hash::{Hash, Hasher};
use std::hash::Hash;
use std::hint::unreachable_unchecked;
use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock, RwLockWriteGuard};
Expand Down
43 changes: 42 additions & 1 deletion src/kernel/src/fs/null/vnode.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use crate::{
errno::{Errno, EISDIR, EROFS},
fs::{
null::hash::NULL_HASHTABLE, perm::Access, Mount, MountFlags, Vnode, VnodeAttrs, VnodeType,
null::hash::NULL_HASHTABLE, perm::Access, Mount, MountFlags, Uio, UioMut, Vnode,
VnodeAttrs, VnodeType,
},
process::VThread,
};
Expand Down Expand Up @@ -89,6 +90,34 @@ impl crate::fs::VnodeBackend for VnodeBackend {

Ok(vnode)
}

fn read(
&self,
_: &Arc<Vnode>,
buf: &mut UioMut,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
let read = self
.lower
.read(buf, td)
.map_err(ReadError::ReadFromLowerFailed)?;

Ok(read)
}

fn write(
&self,
_: &Arc<Vnode>,
buf: &mut Uio,
td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
let written = self
.lower
.write(buf, td)
.map_err(WriteError::WriteFromLowerFailed)?;

Ok(written)
}
}

/// See `null_nodeget` on the PS4 for a reference.
Expand Down Expand Up @@ -149,3 +178,15 @@ pub(super) enum OpenError {

#[derive(Debug, Error, Errno)]
pub(super) enum NodeGetError {}

#[derive(Debug, Error, Errno)]
enum ReadError {
#[error("read from lower vnode failed")]
ReadFromLowerFailed(#[source] Box<dyn Errno>),
}

#[derive(Debug, Error, Errno)]
enum WriteError {
#[error("write from lower vnode failed")]
WriteFromLowerFailed(#[source] Box<dyn Errno>),
}
20 changes: 19 additions & 1 deletion src/kernel/src/fs/tmp/node.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::{AllocVnodeError, TempFs};
use crate::errno::{Errno, ENOENT, ENOSPC};
use crate::fs::{Access, OpenFlags, VFileType, Vnode, VnodeAttrs, VnodeType};
use crate::fs::{Access, Uio, UioMut, Vnode, VnodeAttrs, VnodeType};
use crate::process::VThread;
use gmtx::{Gutex, GutexGroup, GutexWriteGuard};
use macros::Errno;
Expand Down Expand Up @@ -201,6 +201,24 @@ impl crate::fs::VnodeBackend for VnodeBackend {

Ok(vnode)
}

fn read(
&self,
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut UioMut,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}

fn write(
&self,
#[allow(unused_variables)] vn: &Arc<Vnode>,
#[allow(unused_variables)] buf: &mut Uio,
#[allow(unused_variables)] td: Option<&VThread>,
) -> Result<usize, Box<dyn Errno>> {
todo!()
}
}

/// Represents an error when [`Nodes::alloc()`] fails.
Expand Down
21 changes: 21 additions & 0 deletions src/kernel/src/fs/uio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ impl<'a> IoVec<'a> {
_phantom: std::marker::PhantomData,
}
}

pub fn from_slice(slice: &'a mut [u8]) -> Self {
Self {
base: slice.as_ptr(),
len: slice.len(),
_phantom: std::marker::PhantomData,
}
}

pub fn len(&self) -> usize {
self.len
}
}

pub struct Uio<'a> {
Expand Down Expand Up @@ -84,6 +96,15 @@ impl<'a> UioMut<'a> {

Ok(Self { vecs, bytes_left })
}

pub fn from_single_vec(vec: &'a mut IoVec<'a>) -> Self {
let bytes_left = vec.len;

Self {
vecs: std::slice::from_mut(vec),
bytes_left,
}
}
}

#[derive(Debug, Error, Errno)]
Expand Down
Loading

0 comments on commit 807686a

Please sign in to comment.